diff options
Diffstat (limited to 'lib/kernel')
-rw-r--r-- | lib/kernel/doc/src/inet.xml | 26 | ||||
-rw-r--r-- | lib/kernel/src/dist_util.erl | 49 | ||||
-rw-r--r-- | lib/kernel/src/inet.erl | 8 | ||||
-rw-r--r-- | lib/kernel/src/inet_int.hrl | 1 | ||||
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 14 | ||||
-rw-r--r-- | lib/kernel/test/disk_log_SUITE.erl | 50 | ||||
-rw-r--r-- | lib/kernel/test/erl_distribution_wb_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/kernel/test/file_name_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/kernel/test/inet_SUITE.erl | 70 | ||||
-rw-r--r-- | lib/kernel/test/pg2_SUITE.erl | 27 | ||||
-rw-r--r-- | lib/kernel/test/prim_file_SUITE.erl | 47 |
11 files changed, 206 insertions, 94 deletions
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 076e50cd10..947e4d4560 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -897,6 +897,32 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code> <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding/0</c></seealso>.</p></item> </list> </item> + <tag><c>{bind_to_device, Ifname :: binary()}</c></tag> + <item> + <p>Binds a socket to a specific network interface. This option + must be used in a function call that creates a socket, that is, + <seealso marker="gen_tcp#connect/3"><c>gen_tcp:connect/3,4</c></seealso>, + <seealso marker="gen_tcp#listen/2"><c>gen_tcp:listen/2</c></seealso>, + <seealso marker="gen_udp#open/1"><c>gen_udp:open/1,2</c></seealso>, or + <seealso marker="gen_sctp#open/0"><c>gen_sctp:open/0,1,2</c></seealso>.</p> + <p>Unlike <seealso marker="#getifaddrs/0"><c>getifaddrs/0</c></seealso>, Ifname + is encoded a binary. In the unlikely case that a system is using + non-7-bit-ASCII characters in network device names, special care + has to be taken when encoding this argument.</p> + <p>This option uses the Linux-specific socket option + <c>SO_BINDTODEVICE</c>, such as in Linux kernel 2.0.30 or later, + and therefore only exists when the runtime system + is compiled for such an operating system.</p> + <p>Before Linux 3.8, this socket option could be set, but could not retrieved + with <seealso marker="#getopts/2"><c>getopts/2</c></seealso>. Since Linux 3.8, + it is readable.</p> + <p>The virtual machine also needs elevated privileges, either + running as superuser or (for Linux) having capability + <c>CAP_NET_RAW</c>.</p> + <p>The primary use case for this option is to bind sockets into + <url href="http://www.kernel.org/doc/Documentation/networking/vrf.txt">Linux VRF instances</url>. + </p> + </item> <tag><c>list</c></tag> <item> <p>Received <c>Packet</c> is delivered as a list.</p> diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 8d2fc4d4b7..d929179715 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -131,7 +131,7 @@ handshake_other_started(#hs_data{request_type=ReqType}=HSData0) -> other_version=Version, other_node=Node, other_started=true}, - check_dflag_xnc(HSData), + check_dflags(HSData), is_allowed(HSData), ?debug({"MD5 connection from ~p (V~p)~n", [Node, HSData#hs_data.other_version]}), @@ -168,27 +168,24 @@ is_allowed(#hs_data{other_node = Node, %% Check that both nodes can handle the same types of extended %% node containers. If they can not, abort the connection. %% -check_dflag_xnc(#hs_data{other_node = Node, - other_flags = OtherFlags, - other_started = OtherStarted} = HSData) -> - XRFlg = ?DFLAG_EXTENDED_REFERENCES, - XPPFlg = case erlang:system_info(compat_rel) of - R when R >= 10 -> - ?DFLAG_EXTENDED_PIDS_PORTS; - _ -> - 0 - end, - ReqXncFlags = XRFlg bor XPPFlg, - case OtherFlags band ReqXncFlags =:= ReqXncFlags of - true -> - ok; - false -> - What = case {OtherFlags band XRFlg =:= XRFlg, - OtherFlags band XPPFlg =:= XPPFlg} of - {false, false} -> "references, pids and ports"; - {true, false} -> "pids and ports"; - {false, true} -> "references" - end, +check_dflags(#hs_data{other_node = Node, + other_flags = OtherFlags, + other_started = OtherStarted} = HSData) -> + + Mandatory = [{?DFLAG_EXTENDED_REFERENCES, "EXTENDED_REFERENCES"}, + {?DFLAG_EXTENDED_PIDS_PORTS, "EXTENDED_PIDS_PORTS"}, + {?DFLAG_UTF8_ATOMS, "UTF8_ATOMS"}], + Missing = lists:filtermap(fun({Bit, Str}) -> + case Bit band OtherFlags of + Bit -> false; + 0 -> {true, Str} + end + end, + Mandatory), + case Missing of + [] -> + ok; + _ -> case OtherStarted of true -> send_status(HSData, not_allowed), @@ -199,9 +196,9 @@ check_dflag_xnc(#hs_data{other_node = Node, How = "aborted" end, error_msg("** ~w: Connection attempt ~s node ~w ~s " - "since it cannot handle extended ~s. " - "**~n", [node(), Dir, Node, How, What]), - ?shutdown2(Node, {check_dflag_xnc_failed, What}) + "since it cannot handle ~p." + "**~n", [node(), Dir, Node, How, Missing]), + ?shutdown2(Node, {check_dflags_failed, Missing}) end. @@ -327,7 +324,7 @@ handshake_we_started(#hs_data{request_type=ReqType, NewHSData = HSData#hs_data{this_flags = ThisFlags, other_flags = OtherFlags, other_started = false}, - check_dflag_xnc(NewHSData), + check_dflags(NewHSData), MyChallenge = gen_challenge(), {MyCookie,HisCookie} = get_cookies(Node), send_challenge_reply(NewHSData,MyChallenge, diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index f5c13ecdd7..5be790b7d9 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -702,7 +702,7 @@ connect_options() -> header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, - show_econnreset]. + show_econnreset, bind_to_device]. connect_options(Opts, Mod) -> BaseOpts = @@ -770,7 +770,7 @@ listen_options() -> header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, - packet_size, raw, show_econnreset]. + packet_size, raw, show_econnreset, bind_to_device]. listen_options(Opts, Mod) -> BaseOpts = @@ -850,7 +850,7 @@ udp_options() -> deliver, ipv6_v6only, broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop, add_membership, drop_membership, read_packets,raw, - high_msgq_watermark, low_msgq_watermark]. + high_msgq_watermark, low_msgq_watermark, bind_to_device]. udp_options(Opts, Mod) -> @@ -919,6 +919,7 @@ sctp_options() -> [ % The following are generic inet options supported for SCTP sockets: mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark, + bind_to_device, % Other options are SCTP-specific (though they may be similar to their % TCP and UDP counter-parts): @@ -1055,7 +1056,6 @@ binary2filename(Bin) -> Bin end. - translate_ip(any, inet) -> {0,0,0,0}; translate_ip(loopback, inet) -> {127,0,0,1}; translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0}; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index 4e8f59a3b9..e6cd48935a 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -154,6 +154,7 @@ -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). -define(INET_LOPT_LINE_DELIM, 40). -define(INET_OPT_TCLASS, 41). +-define(INET_OPT_BIND_TO_DEVICE, 42). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 19d36a7613..088d851b09 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -107,6 +107,10 @@ init_per_testcase(big_boot_embedded, Config) -> _Else -> {skip, "Needs crypto!"} end; +init_per_testcase(on_load_embedded, Config) -> + LibRoot = code:lib_dir(), + LinkName = filename:join(LibRoot, "on_load_app-1.0"), + [{link_name,LinkName}|Config]; init_per_testcase(_Func, Config) -> P = code:get_path(), [{code_path, P}|Config]. @@ -124,6 +128,10 @@ end_per_testcase(TC, Config) when TC == mult_lib_roots; NodeName = list_to_atom(atom_to_list(TC)++"@"++HostName), test_server:stop_node(NodeName), end_per_testcase(Config); +end_per_testcase(on_load_embedded, Config) -> + LinkName = proplists:get_value(link_name, Config), + _ = del_link(LinkName), + end_per_testcase(Config); end_per_testcase(_Func, Config) -> end_per_testcase(Config). @@ -1271,10 +1279,9 @@ on_load_embedded(Config) when is_list(Config) -> on_load_embedded_1(Config) -> DataDir = proplists:get_value(data_dir, Config), + LinkName = proplists:get_value(link_name, Config), %% Link the on_load_app application into the lib directory. - LibRoot = code:lib_dir(), - LinkName = filename:join(LibRoot, "on_load_app-1.0"), OnLoadApp = filename:join(DataDir, "on_load_app-1.0"), del_link(LinkName), io:format("LinkName :~p, OnLoadApp: ~p~n",[LinkName,OnLoadApp]), @@ -1308,8 +1315,7 @@ on_load_embedded_1(Config) -> ok = rpc:call(Node, on_load_embedded, status, []), %% Clean up. - stop_node(Node), - ok = del_link(LinkName). + stop_node(Node). del_link(LinkName) -> case file:delete(LinkName) of diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 23fe975ef7..079cc2f90f 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -481,7 +481,7 @@ halt_ro_crash(Conf) when is_list(Conf) -> %% This is how it was before R6B: %% {C1,T1,15} = disk_log:chunk(a,start), %% {C2,T2} = disk_log:chunk(a,C1), - {C1,_OneItem,7478} = disk_log:chunk(a,start), + {C1,_OneItem,7476} = disk_log:chunk(a,start), {C2, [], 7} = disk_log:chunk(a,C1), eof = disk_log:chunk(a,C2), ok = disk_log:close(a), @@ -2502,8 +2502,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile = add_ext(File, 2), % current file set_opened(BadFile), - crash(BadFile, 28), % the binary is now invalid - {repaired,n,{recovered,0},{badbytes,26}} = + crash(BadFile, 26), % the binary is now invalid + {repaired,n,{recovered,0},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {40,No}}]), ok = disk_log:close(n), @@ -2518,8 +2518,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile2 = add_ext(File, 1), % current file set_opened(BadFile2), - crash(BadFile2, 51), % the second binary is now invalid - {repaired,n,{recovered,1},{badbytes,26}} = + crash(BadFile2, 47), % the second binary is now invalid + {repaired,n,{recovered,1},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {4000,No}}]), ok = disk_log:close(n), @@ -2571,7 +2571,7 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), set_opened(File), crash(File, 30), - {repaired,n,{recovered,3},{badbytes,16}} = + {repaired,n,{recovered,3},{badbytes,15}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal},{repair,true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), @@ -2797,7 +2797,7 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:log_terms(n, [{some,terms}]), % second file full 2 = curf(n), BadFile = add_ext(File, 1), - crash(BadFile, 28), % the _binary_ is now invalid + crash(BadFile, 26), % the _binary_ is now invalid {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), BadFile = BFile, ok = disk_log:close(n), @@ -2807,7 +2807,7 @@ chunk(Conf) when is_list(Conf) -> {format, internal}]), ok = disk_log:log_terms(n, [{this,is}]), ok = disk_log:sync(n), - crash(File, 28), % the _binary_ is now invalid + crash(File, 26), % the _binary_ is now invalid {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), crash(File, 10), {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), @@ -2901,8 +2901,8 @@ chunk(Conf) when is_list(Conf) -> {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {mode, read_only}]), CrashFile = add_ext(File, 1), - crash(CrashFile, 51), % the binary term {some,terms} is now bad - {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(CrashFile, 46), % the binary term {some,terms} is now bad + {H1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), eof = disk_log:chunk(n, H2), ok = disk_log:close(n), @@ -2916,8 +2916,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 51), % the binary term {some,terms} is now bad - {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(File, 46), % the binary term {some,terms} is now bad + {J1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), eof = disk_log:chunk(n, J2), ok = disk_log:close(n), @@ -2932,8 +2932,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 44), % the binary term {s} is now bad - {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), + crash(File, 40), % the binary term {s} is now bad + {J11, [{this,is}], 6} = disk_log:chunk(n, start, 10), {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), eof = disk_log:chunk(n, J21), ok = disk_log:close(n), @@ -3052,7 +3052,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 6}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3072,7 +3072,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 3}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3181,45 +3181,45 @@ info_current(Conf) when is_list(Conf) -> %% Internal with header. {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head, header}, {size, {100,No}}]), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {1, 1} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {notify, true}, {head, header}, {size, {100,No}}]), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {0, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), rec(1, {disk_log, node(), n, {wrap, 0}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 4} = {no_written_items(n), no_items(n)}, disk_log:inc_wrap_file(n), rec(1, {disk_log, node(), n, {wrap, 0}}), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {3, 4} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. rec(1, {disk_log, node(), n, {wrap, 0}}), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {8, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {12, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. rec(2, {disk_log, node(), n, {wrap, 2}}), - {194, 2} = {curb(n), cur_cnt(n)}, + {193, 2} = {curb(n), cur_cnt(n)}, {16, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [SB,SB,SB]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {80, 4} = {curb(n), cur_cnt(n)}, + {79, 4} = {curb(n), cur_cnt(n)}, {20, 9} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), del(File, No), diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index 61aa3b32ee..c1dc208cc1 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -56,10 +56,14 @@ -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). -define(DFLAG_NEW_FUN_TAGS,16#80). -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_UTF8_ATOMS, 16#10000). %% From R9 and forward extended references is compulsory %% From R10 and forward extended pids and ports are compulsory --define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). +%% From R20 and forward UTF8 atoms are compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor + ?DFLAG_EXTENDED_PIDS_PORTS bor + ?DFLAG_UTF8_ATOMS)). -define(shutdown(X), exit(X)). diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 10b6b105d0..b2051af050 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -383,7 +383,7 @@ check_icky(Mod) -> ok end, - _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir">>)), + _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)), if UniMode and (OS =/= win32) -> {error,enoent} = Mod:set_cwd("åäö_dir"); diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index f60c13d2e3..86f6b95fb9 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -40,7 +40,8 @@ lookup_bad_search_option/1, getif/1, getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1, - parse_strict_address/1, simple_netns/1, simple_netns_open/1]). + parse_strict_address/1, simple_netns/1, simple_netns_open/1, + simple_bind_to_device/1, simple_bind_to_device_open/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0, test_netns/0]). @@ -58,7 +59,8 @@ all() -> gethostnative_debug_level, gethostnative_soft_restart, lookup_bad_search_option, getif, getif_ifr_name_overflow, getservbyname_overflow, - getifaddrs, parse_strict_address, simple_netns, simple_netns_open]. + getifaddrs, parse_strict_address, simple_netns, simple_netns_open, + simple_bind_to_device, simple_bind_to_device_open]. groups() -> [{parse, [], [parse_hosts, parse_address]}]. @@ -1247,3 +1249,67 @@ cmd(CmdString) -> io:put_chars(["# ",CmdString,io_lib:nl()]), io:put_chars([os:cmd(CmdString++" ; echo ' =>' $?")]), ok. + +-define(CAP_NET_RAW, 13). %% from /usr/include/linux/capability.h + +can_bind_to_device({unix, linux}, {Major, _, _}) + when Major > 2 -> + Status = os:cmd("cat /proc/self/status | grep CapEff"), + [_, CapEffStr] = string:tokens(Status, [$\n, $\t]), + CapEff = list_to_integer(CapEffStr, 16), + if CapEff band (1 bsl ?CAP_NET_RAW) =/= 0 -> + ok; + true -> + {skip,"insufficient capabilities, CAP_NET_RAW not granted"} + end; +can_bind_to_device(_OS, _Version) -> + {skip,"socket option bind_to_device not supported on this OS or version"}. + +simple_bind_to_device(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0), + jog_bind_to_device_opt(U), + ok = gen_udp:close(U), + %% + {ok,L} = gen_tcp:listen(0, []), + jog_bind_to_device_opt(L), + ok = gen_tcp:close(L), + %% + case gen_sctp:open() of + {ok,S} -> + jog_bind_to_device_opt(S), + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +%% Smoke test bind_to_device support. +simple_bind_to_device_open(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_udp:close(U), + {ok,T} = gen_tcp:listen(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_tcp:close(T), + + case gen_sctp:open(0, [binary,{bind_to_device,<<"lo">>},inet]) of + {ok,S} -> + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +jog_bind_to_device_opt(S) -> + %% This is just jogging the option mechanics + ok = inet:setopts(S, [{bind_to_device,<<>>}]), + {ok,[{bind_to_device,<<>>}]} = inet:getopts(S, [bind_to_device]), + ok = inet:setopts(S, [{bind_to_device,<<"lo">>}]), + {ok,[{bind_to_device,<<"lo">>}]} = inet:getopts(S, [bind_to_device]), + ok. diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl index fdc268cb5a..9460608a3e 100644 --- a/lib/kernel/test/pg2_SUITE.erl +++ b/lib/kernel/test/pg2_SUITE.erl @@ -31,7 +31,7 @@ -export([ otp_7277/1, otp_8259/1, otp_8653/1, - compat/1, basic/1]). + basic/1]). -define(TESTCASE, testcase_name). -define(testcase, proplists:get_value(?TESTCASE, Config)). @@ -56,7 +56,7 @@ all() -> groups() -> [{tickets, [], - [otp_7277, otp_8259, otp_8653, compat, basic]}]. + [otp_7277, otp_8259, otp_8653, basic]}]. init_per_suite(Config) -> Config. @@ -218,29 +218,6 @@ loop() -> exit(normal) end. -%% OTP-8259. Check that 'exchange' and 'del_member' work. -compat(Config) when is_list(Config) -> - case test_server:is_release_available("r13b") of - true -> - Pid = spawn(forever()), - G = a, - ok = pg2:create(G), - ok = pg2:join(G, Pid), - ok = pg2:join(G, Pid), - {ok, A} = start_node_rel(r13, r13b, slave), - pong = net_adm:ping(A), - wait_for_ready_net(Config), - {ok, _} = rpc:call(A, pg2, start, []), - ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])), - true = exit(Pid, kill), - ?UNTIL([] =:= pg2:get_members(a)), - ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])), - test_server:stop_node(A), - ok; - false -> - {skipped, "No support for old node"} - end. - %% OTP-8259. Some basic tests. basic(Config) when is_list(Config) -> _ = [pg2:delete(G) || G <- pg2:which_groups()], diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 8be94f1e57..0c84a7d1cc 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -19,8 +19,8 @@ %% -module(prim_file_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - read_write_file/1]). + init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2, + read_write_file/1, free_memory/0]). -export([cur_dir_0a/1, cur_dir_0b/1, cur_dir_1a/1, cur_dir_1b/1, make_del_dir_a/1, make_del_dir_b/1, @@ -115,6 +115,18 @@ groups() -> [make_link_a, make_link_b, read_link_info_for_non_link, symlinks_a, symlinks_b, list_dir_error]}]. +init_per_testcase(large_write, Config) -> + {ok, Started} = application:ensure_all_started(os_mon), + [{started, Started}|Config]; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(large_write, Config) -> + [application:stop(App) || App <- lists:reverse(proplists:get_value(started, Config))], + ok; +end_per_testcase(_, _Config) -> + ok. + init_per_group(_GroupName, Config) -> Config. @@ -2022,11 +2034,13 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = unix_free(proplists:get_value(priv_dir, Config)), - io:format("Free disk: ~w KByte~n", [N]), - if N < 5 bsl 20 -> + DiscFree = unix_free(proplists:get_value(priv_dir, Config)), + MemFree = free_memory(), + io:format("Free disk: ~w KByte~n", [DiscFree]), + io:format("Free mem: ~w MByte~n", [MemFree]), + if DiscFree < 5 bsl 20; MemFree < 5 bsl 10 -> %% Less than 5 GByte free - {skip,"Less than 5 GByte free disk"}; + {skip,"Less than 5 GByte free disk/mem"}; true -> do_run_large_file_test(Config, Run, Name) end; @@ -2079,6 +2093,27 @@ zip_data([], Bs) -> zip_data(As, []) -> As. +%% Stolen from emulator -> alloc_SUITE +free_memory() -> + %% Free memory in MB. + try + SMD = memsup:get_system_memory_data(), + {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD), + TotFree = (Free + + case lists:keysearch(cached_memory, 1, SMD) of + {value, {cached_memory, Cached}} -> Cached; + false -> 0 + end + + case lists:keysearch(buffered_memory, 1, SMD) of + {value, {buffered_memory, Buffed}} -> Buffed; + false -> 0 + end), + TotFree div (1024*1024) + catch + error : undef -> + ct:fail({"os_mon not built"}) + end. + %%%----------------------------------------------------------------- %%% Utilities rm_rf(Mod,Dir) -> |