diff options
author | Anders Svensson <[email protected]> | 2017-03-30 16:29:02 +0200 |
---|---|---|
committer | Anders Svensson <[email protected]> | 2017-06-11 16:30:35 +0200 |
commit | 1df74351286b6cd0e2b673fdf07f7219244ce9a7 (patch) | |
tree | b3c82af8c828656260d097f9ae3304e7be653733 | |
parent | 111261d15df900bedd544ba1fab3a5880abda70a (diff) | |
download | otp-1df74351286b6cd0e2b673fdf07f7219244ce9a7.tar.gz otp-1df74351286b6cd0e2b673fdf07f7219244ce9a7.tar.bz2 otp-1df74351286b6cd0e2b673fdf07f7219244ce9a7.zip |
Work around SCTP quirks on sparc-sun-solaris2.10
This addresses the testcase failures mentioned in the parent commit,
which has been on account of the behaviour below, in which connect fails
on the loopback address. Work around it by finding/using another address
if possible.
$ erl
Erlang/OTP 20 [DEVELOPMENT] [erts-9.0] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false] [sharing-preserving]
Eshell V9.0 (abort with ^G)
1> {ok, LP} = gen_sctp:open().
{ok,#Port<0.439>}
2> gen_sctp:listen(LP, true).
ok
3> inet:socknames(LP).
{ok,[{{10,67,16,178},36506},{{127,0,0,1},36506}]}
4> {ok, S} = gen_sctp:open([{ip, {127,0,0,1}}]).
{ok,#Port<0.443>}
5> gen_sctp:connect_init(S, {127,0,0,1}, 36506, []).
{error,eaddrnotavail}
6> gen_sctp:connect_init(S, {10,67,16,178}, 36506, []).
{error,eaddrnotavail}
7> gen_sctp:close(S).
ok
8> f(S).
ok
9> {ok, S} = gen_sctp:open().
{ok,#Port<0.444>}
10> gen_sctp:connect_init(S, {127,0,0,1}, 36506, []).
ok
Even the following has been seen on at least one host, so that success
of gen_sctp:open/0 is no guarantee.
$ ifconfig -a4
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
bge0: flags=1004843<UP,BROADCAST,RUNNING,MULTICAST,DHCP,IPv4> mtu 1500 index 2
inet 10.67.16.180 netmask ffffff00 broadcast 10.67.16.255
$ erl
Erlang/OTP 20 [DEVELOPMENT] [erts-9.0] [source] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.0 (abort with ^G)
1> {ok, S} = gen_sctp:open(),
1> gen_sctp:connect(S, {127,0,0,1}, 3868, []).
{error,eafnosupport}
2> gen_sctp:connect(S, {10,67,16,180}, 3868, []).
{error,eafnosupport}
-rw-r--r-- | lib/diameter/test/diameter_examples_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/diameter/test/diameter_transport_SUITE.erl | 46 | ||||
-rw-r--r-- | lib/diameter/test/diameter_util.erl | 50 |
3 files changed, 66 insertions, 38 deletions
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl index e4ed2b227d..680ce4f366 100644 --- a/lib/diameter/test/diameter_examples_SUITE.erl +++ b/lib/diameter/test/diameter_examples_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2015. All Rights Reserved. +%% Copyright Ericsson AB 2013-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -70,6 +70,8 @@ %% Transport protocols over which the example Diameter nodes are run. -define(PROTS, [tcp, sctp]). +-define(ADDR, diameter_util:ip4()). + %% =========================================================================== suite() -> @@ -346,7 +348,7 @@ top(Dir, LibDir) -> start({server, Prot}) -> ok = diameter:start(), ok = server:start(), - {ok, Ref} = server:listen(Prot), + {ok, Ref} = server:listen({Prot, ?ADDR, 3868}), [_] = ?util:lport(Prot, Ref), ok; @@ -354,7 +356,7 @@ start({client = Svc, Prot}) -> ok = diameter:start(), true = diameter:subscribe(Svc), ok = client:start(), - {ok, Ref} = client:connect(Prot), + {ok, Ref} = client:connect({Prot, ?ADDR, ?ADDR, 3868}), receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end; start(Config) -> diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl index c94f46b7a5..ac65cbe618 100644 --- a/lib/diameter/test/diameter_transport_SUITE.erl +++ b/lib/diameter/test/diameter_transport_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -56,8 +56,10 @@ -define(RECV(Pat, Ret), receive Pat -> Ret end). -define(RECV(Pat), ?RECV(Pat, diameter_lib:now())). -%% Sockets are opened on the loopback address. --define(ADDR, {127,0,0,1}). +%% Address to open sockets on. +-define(ADDR(Prot), if sctp == Prot -> diameter_util:ip4(); + true -> {127,0,0,1} + end). %% diameter_tcp doesn't use anything but host_ip_address, and that %% only is a local address isn't configured as at transport start. @@ -351,13 +353,14 @@ rand_bytes(N, Bin) -> %% start_connect/3 start_connect(Prot, PortNr, Ref) -> - {ok, TPid, [?ADDR]} = start_connect(Prot, - {connect, Ref}, - ?SVC([]), - [{raddr, ?ADDR}, - {rport, PortNr}, - {ip, ?ADDR}, - {port, 0}]), + Addr = ?ADDR(Prot), + {ok, TPid, [_]} = start_connect(Prot, + {connect, Ref}, + ?SVC([]), + [{raddr, Addr}, + {rport, PortNr}, + {ip, Addr}, + {port, 0}]), ?RECV(?TMSG({TPid, connected, _})), TPid. @@ -370,9 +373,9 @@ start_connect(tcp, T, Svc, Opts) -> start_accept(Prot, Ref) -> {Mod, Opts} = tmod(Prot), - {ok, TPid, [?ADDR]} = Mod:start({accept, Ref}, - ?SVC([?ADDR]), - [{port, 0} | Opts]), + {ok, TPid, [_]} = Mod:start({accept, Ref}, + ?SVC([?ADDR(Prot)]), + [{port, 0} | Opts]), ?RECV(?TMSG({TPid, connected})), TPid. @@ -386,19 +389,20 @@ tmod(tcp) -> %% gen_connect/2 gen_connect(sctp = P, PortNr) -> - {ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]), - ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []), + Addr = ?ADDR(P), + {ok, Sock} = Ok = gen_sctp:open([{ip, Addr}, {port, 0} | ?SCTP_OPTS]), + ok = gen_sctp:connect_init(Sock, Addr, PortNr, []), Ok = gen_accept(P, Sock); -gen_connect(tcp, PortNr) -> - gen_tcp:connect(?ADDR, PortNr, ?TCP_OPTS). +gen_connect(tcp = P, PortNr) -> + gen_tcp:connect(?ADDR(P), PortNr, ?TCP_OPTS). %% gen_listen/1 -gen_listen(sctp) -> - {ok, Sock} = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]), +gen_listen(sctp = P) -> + {ok, Sock} = gen_sctp:open([{ip, ?ADDR(P)}, {port, 0} | ?SCTP_OPTS]), {gen_sctp:listen(Sock, true), Sock}; -gen_listen(tcp) -> - gen_tcp:listen(0, [{ip, ?ADDR} | ?TCP_OPTS]). +gen_listen(tcp = P) -> + gen_tcp:listen(0, [{ip, ?ADDR(P)} | ?TCP_OPTS]). %% gen_accept/2 diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl index 37fcbbc267..8df5c907d0 100644 --- a/lib/diameter/test/diameter_util.erl +++ b/lib/diameter/test/diameter_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -32,7 +32,8 @@ foldl/3, scramble/1, unique_string/0, - have_sctp/0]). + have_sctp/0, + ip4/0]). %% diameter-specific -export([lport/2, @@ -197,8 +198,11 @@ unique_string() -> have_sctp() -> case gen_sctp:open() of {ok, Sock} -> + RC = gen_sctp:connect(Sock, ip4(), 3868, []), gen_sctp:close(Sock), - true; + %% Connect has been seen to return eafnosupport on at least + %% one SunOS 10 Sparc host, for reasons unknown. + RC /= {error, eafnosupport}; {error, E} when E == eprotonosupport; E == esocktnosupport -> %% fail on any other reason false @@ -361,7 +365,8 @@ tmod(any) -> opts(Prot, T) -> tmo(T, lists:append([[{transport_module, M}, {transport_config, C}] || M <- tmod(Prot), - C <- [cfg(M,T) ++ cfg(M) ++ cfg(T)]])). + C <- [buf(M,T) ++ [{ip, addr(M)}, {port, 0}] + ++ remote(M,T)]])). tmo(listen, Opts) -> Opts; @@ -377,21 +382,38 @@ tmo([M, C | Opts]) -> %% Listening SCTP socket need larger-than-default buffers to avoid %% resends on some platforms (eg. SLES 11). -cfg(diameter_sctp, listen) -> +buf(diameter_sctp, listen) -> [{recbuf, 1 bsl 16}, {sndbuf, 1 bsl 16}]; - -cfg(_, _) -> +buf(_, _) -> []. -cfg(M) - when M == diameter_tcp; - M == diameter_sctp -> - [{ip, ?ADDR}, {port, 0}]; +addr(diameter_tcp) -> + {127,0,0,1}; +addr(diameter_sctp) -> + ip4(). -cfg(listen) -> +remote(_, listen) -> [{accept, M} || M <- [{256,0,0,1}, ["256.0.0.1", ["^.+$"]]]]; -cfg(PortNr) -> - [{raddr, ?ADDR}, {rport, PortNr}]. +remote(Mod, PortNr) -> + [{raddr, addr(Mod)}, {rport, PortNr}]. + +%% Try to use something other than the loopback address where this +%% address is known to be problematic for gen_sctp. +ip4() -> + try + "sparc-sun-solaris2.10" = erlang:system_info(system_architecture), + {ok, List} = inet:getifaddrs(), + hd(lists:flatmap(fun ip4/1, List)) + catch + error:_ -> + ?ADDR + end. + +ip4({_, Opts}) -> + {flags, Flags} = lists:keyfind(flags, 1, Opts), + [A || lists:member(up, Flags), + not lists:member(loopback, Flags), + {addr, {_,_,_,_} = A} <- Opts]. %% --------------------------------------------------------------------------- %% info/0 |