summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicael Karlberg <bmk@erlang.org>2019-09-12 12:50:30 +0200
committerMicael Karlberg <bmk@erlang.org>2019-09-12 16:09:38 +0200
commita57bf61158accddbde6c67b402bcf47f48c5b670 (patch)
tree5f5c92eb8e889b4ee2ab40ff54249e2a9b928030
parent4e5a593041a8aa1f616dfcb3357238c78f56a54c (diff)
downloaderlang-a57bf61158accddbde6c67b402bcf47f48c5b670.tar.gz
[snmp|manager|test] Add test cases using the new (cbproxy) feature
Add some test cases that exercise the new (cbproxy) feature. OTP-15947
-rw-r--r--lib/snmp/test/snmp_manager_test.erl308
-rw-r--r--lib/snmp/test/snmp_test_lib.erl65
2 files changed, 290 insertions, 83 deletions
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 6ced55f0cc..77698d1f99 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -80,21 +80,27 @@
simple_sync_get_next3/1,
simple_async_get_next1/1,
simple_async_get_next2/1,
- simple_async_get_next3/1,
+ simple_async_get_next3_cbp_def/1,
+ simple_async_get_next3_cbp_temp/1,
+ simple_async_get_next3_cbp_perm/1,
simple_sync_set1/1,
simple_sync_set2/1,
simple_sync_set3/1,
simple_async_set1/1,
simple_async_set2/1,
- simple_async_set3/1,
+ simple_async_set3_cbp_def/1,
+ simple_async_set3_cbp_temp/1,
+ simple_async_set3_cbp_perm/1,
simple_sync_get_bulk1/1,
simple_sync_get_bulk2/1,
simple_sync_get_bulk3/1,
simple_async_get_bulk1/1,
simple_async_get_bulk2/1,
- simple_async_get_bulk3/1,
+ simple_async_get_bulk3_cbp_def/1,
+ simple_async_get_bulk3_cbp_temp/1,
+ simple_async_get_bulk3_cbp_perm/1,
misc_async1/1,
misc_async2/1,
@@ -108,7 +114,9 @@
inform2/1,
inform3/1,
inform4/1,
- inform_swarm/1,
+ inform_swarm_cbp_def/1,
+ inform_swarm_cbp_temp/1,
+ inform_swarm_cbp_perm/1,
report/1,
@@ -253,8 +261,19 @@ init_per_testcase2(Case, Config) ->
Family = proplists:get_value(ipfamily, Config, inet),
- Conf = [{watchdog, ?WD_START(?MINS(5))},
- {ipfamily, Family},
+ TO = case Case of
+ inform3 ->
+ ?MINS(2);
+ InformSwarm when (InformSwarm =:= inform_swarm_cbp_def) orelse
+ (InformSwarm =:= inform_swarm_cbp_temp) orelse
+ (InformSwarm =:= inform_swarm_cbp_perm) ->
+ ?MINS(60);
+ _ ->
+ ?MINS(1)
+ end,
+ ct:timetrap(TO),
+
+ Conf = [{ipfamily, Family},
{ip, ?LOCALHOST(Family)},
{case_top_dir, CaseTopDir},
{agent_dir, AgTopDir},
@@ -287,13 +306,19 @@ init_per_testcase3(Case, Config) ->
ApiCases03 =
[
simple_sync_get3,
- simple_async_get3,
- simple_sync_get_next3,
- simple_async_get_next3,
- simple_sync_set3,
- simple_async_set3,
- simple_sync_get_bulk3,
- simple_async_get_bulk3
+ simple_async_get3,
+ simple_sync_get_next3,
+ simple_async_get_next3_cbp_def,
+ simple_async_get_next3_cbp_temp,
+ simple_async_get_next3_cbp_perm,
+ simple_sync_set3,
+ simple_async_set3_cbp_def,
+ simple_async_set3_cbp_temp,
+ simple_async_set3_cbp_perm,
+ simple_sync_get_bulk3,
+ simple_async_get_bulk3_cbp_def,
+ simple_async_get_bulk3_cbp_temp,
+ simple_async_get_bulk3_cbp_perm
],
Cases =
[
@@ -303,17 +328,26 @@ init_per_testcase3(Case, Config) ->
inform2,
inform3,
inform4,
- inform_swarm,
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm,
report
] ++
ApiCases02 ++
ApiCases03,
case lists:member(Case, Cases) of
true ->
- NoAutoInformCases = [inform1, inform2, inform3, inform_swarm],
+ NoAutoInformCases = [inform1, inform2, inform3,
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm],
AutoInform = not lists:member(Case, NoAutoInformCases),
Conf1 = if
- Case =:= inform_swarm ->
+ %% We turn off verbosity for the swarm cases
+ %% (too much output).
+ (Case =:= inform_swarm_cbp_def) orelse
+ (Case =:= inform_swarm_cbp_temp) orelse
+ (Case =:= inform_swarm_cbp_perm) ->
Verb = [{manager_config_verbosity, silence},
{manager_note_store_verbosity, silence},
{manager_server_verbosity, info},
@@ -326,14 +360,28 @@ init_per_testcase3(Case, Config) ->
true ->
Config
end,
- Conf2 = init_agent(Conf1),
- Conf3 = init_manager(AutoInform, Conf2),
- Conf4 = init_mgr_user(Conf3),
+ Conf2 = if
+ (Case =:= simple_async_get_next3_cbp_temp) orelse
+ (Case =:= simple_async_set3_cbp_temp) orelse
+ (Case =:= simple_async_get_bulk3_cbp_temp) orelse
+ (Case =:= inform_swarm_cbp_temp) ->
+ [{manager_server_cbproxy, temporary} | Conf1];
+ (Case =:= simple_async_get_next3_cbp_perm) orelse
+ (Case =:= simple_async_set3_cbp_perm) orelse
+ (Case =:= simple_async_get_bulk3_cbp_perm) orelse
+ (Case =:= inform_swarm_cbp_perm) ->
+ [{manager_server_cbproxy, permanent} | Conf1];
+ true ->
+ Conf1
+ end,
+ Conf3 = init_agent(Conf2),
+ Conf4 = init_manager(AutoInform, Conf3),
+ Conf5 = init_mgr_user(Conf4),
case lists:member(Case, ApiCases02 ++ ApiCases03) of
true ->
- init_mgr_user_data2(Conf4);
+ init_mgr_user_data2(Conf5);
false ->
- init_mgr_user_data1(Conf4)
+ init_mgr_user_data1(Conf5)
end;
false ->
Config
@@ -343,13 +391,12 @@ end_per_testcase(Case, Config) when is_list(Config) ->
p(Case, "end_per_testcase begin when"
"~n Nodes: ~p~n~n", [erlang:nodes()]),
?DBG("fin [~w] Nodes [1]: ~p", [Case, erlang:nodes()]),
- Dog = ?config(watchdog, Config),
- ?WD_STOP(Dog),
- Conf1 = lists:keydelete(watchdog, 1, Config),
+ %% Dog = ?config(watchdog, Config),
+ %% ?WD_STOP(Dog),
+ %% Conf1 = lists:keydelete(watchdog, 1, Config),
+ Conf1 = Config,
Conf2 = end_per_testcase2(Case, Conf1),
?DBG("fin [~w] Nodes [2]: ~p", [Case, erlang:nodes()]),
- %% TopDir = ?config(top_dir, Conf2),
- %% ?DEL_DIR(TopDir),
p(Case, "end_per_testcase end when"
"~n Nodes: ~p~n~n", [erlang:nodes()]),
Conf2.
@@ -373,11 +420,17 @@ end_per_testcase2(Case, Config) ->
simple_sync_get3,
simple_async_get3,
simple_sync_get_next3,
- simple_async_get_next3,
+ simple_async_get_next3_cbp_def,
+ simple_async_get_next3_cbp_temp,
+ simple_async_get_next3_cbp_perm,
simple_sync_set3,
- simple_async_set3,
+ simple_async_set3_cbp_def,
+ simple_async_set3_cbp_temp,
+ simple_async_set3_cbp_perm,
simple_sync_get_bulk3,
- simple_async_get_bulk3
+ simple_async_get_bulk3_cbp_def,
+ simple_async_get_bulk3_cbp_temp,
+ simple_async_get_bulk3_cbp_perm
],
Cases =
[
@@ -387,7 +440,9 @@ end_per_testcase2(Case, Config) ->
inform2,
inform3,
inform4,
- inform_swarm,
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm,
report
] ++
ApiCases02 ++
@@ -487,12 +542,14 @@ groups() ->
},
{get_next_tests, [],
[
- simple_sync_get_next1,
+ simple_sync_get_next1,
simple_sync_get_next2,
simple_sync_get_next3,
- simple_async_get_next1,
- simple_async_get_next2,
- simple_async_get_next3
+ simple_async_get_next1,
+ simple_async_get_next2,
+ simple_async_get_next3_cbp_def,
+ simple_async_get_next3_cbp_temp,
+ simple_async_get_next3_cbp_perm
]
},
{set_tests, [],
@@ -501,8 +558,10 @@ groups() ->
simple_sync_set2,
simple_sync_set3,
simple_async_set1,
- simple_async_set2,
- simple_async_set3
+ simple_async_set2,
+ simple_async_set3_cbp_def,
+ simple_async_set3_cbp_temp,
+ simple_async_set3_cbp_perm
]
},
{bulk_tests, [],
@@ -512,7 +571,9 @@ groups() ->
simple_sync_get_bulk3,
simple_async_get_bulk1,
simple_async_get_bulk2,
- simple_async_get_bulk3
+ simple_async_get_bulk3_cbp_def,
+ simple_async_get_bulk3_cbp_temp,
+ simple_async_get_bulk3_cbp_perm
]
},
{misc_request_tests, [],
@@ -529,7 +590,9 @@ groups() ->
inform2,
inform3,
inform4,
- inform_swarm,
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm,
report
]
},
@@ -541,7 +604,9 @@ groups() ->
inform2,
inform3,
inform4,
- inform_swarm,
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm,
report
]
},
@@ -576,10 +641,14 @@ ipv6_tests() ->
simple_sync_set3,
simple_async_set2,
simple_sync_get_bulk2,
- simple_async_get_bulk3,
+ simple_async_get_bulk3_cbp_def,
+ simple_async_get_bulk3_cbp_temp,
+ simple_async_get_bulk3_cbp_perm,
misc_async2,
inform1,
- inform_swarm
+ inform_swarm_cbp_def,
+ inform_swarm_cbp_temp,
+ inform_swarm_cbp_perm
].
@@ -2550,13 +2619,32 @@ async_gn_exec2(Node, TargetName, Oids) ->
%%======================================================================
-simple_async_get_next3(doc) ->
+simple_async_get_next3_cbp_def(doc) ->
+ ["Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_next3_cbp_def(suite) -> [];
+simple_async_get_next3_cbp_def(Config) when is_list(Config) ->
+ put(tname, ssgn2_cbp_def),
+ simple_async_get_next3(Config).
+
+simple_async_get_next3_cbp_temp(doc) ->
+ ["Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_next3_cbp_temp(suite) -> [];
+simple_async_get_next3_cbp_temp(Config) when is_list(Config) ->
+ put(tname, ssgn2_cbp_temp),
+ simple_async_get_next3(Config).
+
+simple_async_get_next3_cbp_perm(doc) ->
["Simple (async) get_next-request - "
"Version 3 API (TargetName with send-opts)"];
-simple_async_get_next3(suite) -> [];
+simple_async_get_next3_cbp_perm(suite) -> [];
+simple_async_get_next3_cbp_perm(Config) when is_list(Config) ->
+ put(tname, ssgn2_cbp_perm),
+ simple_async_get_next3(Config).
+
simple_async_get_next3(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- put(tname, ssgn2),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2934,12 +3022,29 @@ async_s_exec2(Node, TargetName, VAVs) ->
%%======================================================================
-simple_async_set3(doc) ->
+simple_async_set3_cbp_def(doc) ->
+ ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
+simple_async_set3_cbp_def(suite) -> [];
+simple_async_set3_cbp_def(Config) when is_list(Config) ->
+ put(tname, sas3_cbp_def),
+ simple_async_set3(Config).
+
+simple_async_set3_cbp_temp(doc) ->
+ ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
+simple_async_set3_cbp_temp(suite) -> [];
+simple_async_set3_cbp_temp(Config) when is_list(Config) ->
+ put(tname, sas3_cbp_temp),
+ simple_async_set3(Config).
+
+simple_async_set3_cbp_perm(doc) ->
["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
-simple_async_set3(suite) -> [];
-simple_async_set3(Config) when is_list(Config) ->
+simple_async_set3_cbp_perm(suite) -> [];
+simple_async_set3_cbp_perm(Config) when is_list(Config) ->
+ put(tname, sas3_cbp_perm),
+ simple_async_set3(Config).
+
+simple_async_set3(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- put(tname, sas3),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3646,13 +3751,16 @@ async_gb_exec2(Node, TargetName, {NR, MR, Oids}) ->
%%======================================================================
-simple_async_get_bulk3(doc) ->
+simple_async_get_bulk3_cbp_def(doc) ->
["Simple (async) get_bulk-request - "
"Version 3 API (TargetName with send-opts)"];
-simple_async_get_bulk3(suite) -> [];
-simple_async_get_bulk3(Config) when is_list(Config) ->
+simple_async_get_bulk3_cbp_def(suite) -> [];
+simple_async_get_bulk3_cbp_def(Config) when is_list(Config) ->
+ put(tname, sagb3_cbp_def),
+ simple_async_get_bulk3(Config).
+
+simple_async_get_bulk3(Config) ->
process_flag(trap_exit, true),
- put(tname, sagb3),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3691,6 +3799,28 @@ async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) ->
%%======================================================================
+simple_async_get_bulk3_cbp_temp(doc) ->
+ ["Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_bulk3_cbp_temp(suite) -> [];
+simple_async_get_bulk3_cbp_temp(Config) when is_list(Config) ->
+ put(tname, sagb3_cbp_temp),
+ simple_async_get_bulk3([{manager_server_cbproxy, temporary}|Config]).
+
+
+%%======================================================================
+
+simple_async_get_bulk3_cbp_perm(doc) ->
+ ["Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_bulk3_cbp_perm(suite) -> [];
+simple_async_get_bulk3_cbp_perm(Config) when is_list(Config) ->
+ put(tname, sagb3_cbp_perm),
+ simple_async_get_bulk3([{manager_server_cbproxy, permanent}|Config]).
+
+
+%%======================================================================
+
misc_async1(doc) -> ["Misc (async) request(s) - "
"Old style (Addr & Port)"];
misc_async1(suite) -> [];
@@ -5034,12 +5164,25 @@ inform4(Config) when is_list(Config) ->
%%======================================================================
%%
-%% Test: ts:run(snmp, snmp_manager_test, inform_swarm, [batch]).
+%% Test: ts:run(snmp, snmp_manager_test, inform_swarm_cbp_def, [batch]).
-inform_swarm(suite) -> [];
-inform_swarm(Config) when is_list(Config) ->
+inform_swarm_cbp_def(suite) -> [];
+inform_swarm_cbp_def(Config) when is_list(Config) ->
+ put(tname, is_cbp_def),
+ inform_swarm(Config).
+
+inform_swarm_cbp_temp(suite) -> [];
+inform_swarm_cbp_temp(Config) when is_list(Config) ->
+ put(tname, is_cbp_temp),
+ inform_swarm([{manager_server_cbproxy, temporary}|Config]).
+
+inform_swarm_cbp_perm(suite) -> [];
+inform_swarm_cbp_perm(Config) when is_list(Config) ->
+ put(tname, is_cbp_perm),
+ inform_swarm([{manager_server_cbproxy, permanent}|Config]).
+
+inform_swarm(Config) ->
process_flag(trap_exit, true),
- put(tname, is),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -5055,7 +5198,7 @@ inform_swarm(Config) when is_list(Config) ->
?line ok = agent_load_mib(AgentNode, Test2Mib),
?line ok = agent_load_mib(AgentNode, TestTrapMib),
?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
- NumInforms = 100,
+ NumInforms = 100000,
Collector = self(),
@@ -5077,10 +5220,13 @@ inform_swarm(Config) when is_list(Config) ->
[]),
%% Sleep some [(N div 10)*100 ms]
%% every tenth notification
- if
+ if
+ N rem 100 == 0 ->
+ Sleep = 1000,
+ p("sleep ~w [~w]", [Sleep, N]),
+ ?SLEEP(Sleep);
N rem 10 == 0 ->
- %% Time to sleep some
- Sleep = (N div 10) * 50,
+ Sleep = 100,
p("sleep ~w [~w]", [Sleep, N]),
?SLEEP(Sleep);
true ->
@@ -5140,17 +5286,17 @@ inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, _)
(N == RespCnt) and
(N =< RecvCnt)) ->
p("inform_swarm_collector -> done when"
- "~n N: ~w"
- "~n SentAckCnt: ~w"
- "~n RecvCnt: ~w"
- "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]),
+ "~n N: ~w"
+ "~n SentAckCnt: ~w"
+ "~n RecvCnt: ~w"
+ "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]),
ok;
inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) ->
p("inform_swarm_collector -> entry with"
- "~n N: ~w"
- "~n SentAckCnt: ~w"
- "~n RecvCnt: ~w"
- "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]),
+ "~n N: ~w"
+ "~n SentAckCnt: ~w"
+ "~n RecvCnt: ~w"
+ "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]),
receive
{snmp_targets, {inform2_tag1, Id}, [_Addr]} ->
p("received inform-sent acknowledgement for ~w", [Id]),
@@ -5167,18 +5313,18 @@ inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) ->
Timeout);
{Err, Idx, VBs} ->
p("<ERROR> unexpected error status: "
- "~n Err: ~p"
- "~n Idx: ~p"
- "~n VBs: ~p", [Err, Idx, VBs]),
+ "~n Err: ~p"
+ "~n Idx: ~p"
+ "~n VBs: ~p", [Err, Idx, VBs]),
Reason = {unexpected_status, {Err, Idx, VBs}},
{error, Reason}
end;
%% The agent has received ack from the manager
{snmp_notification, {inform2_tag1, Id}, {got_response, Addr}} ->
- p("received expected \"got response\" for ~w"
+ p("received expected \"got response\" for ~w "
"notification from: "
- "~n ~p",
+ "~n ~p",
[Id, Addr]),
inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt+1,
Timeout);
@@ -5187,7 +5333,7 @@ inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) ->
{snmp_notification, inform2_tag1, {no_response, Addr}} ->
p("<ERROR> received expected \"no response\" notification "
"from: "
- "~n ~p", [Addr]),
+ "~n ~p", [Addr]),
Reason = {no_response, Addr, {N, SentAckCnt, RecvCnt, RespCnt}},
{error, Reason}
@@ -5373,11 +5519,11 @@ command_handler([{No, Desc, Cmd}|Cmds]) ->
%% -- Misc manager functions --
init_manager(AutoInform, Config) ->
+
?LOG("init_manager -> entry with"
"~n AutoInform: ~p"
"~n Config: ~p", [AutoInform, Config]),
-
%% --
%% Start node
%%
@@ -6089,16 +6235,17 @@ mgr_user_name_to_oid(Node, Name) ->
start_manager(Node, Vsns, Config) ->
start_manager(Node, Vsns, Config, []).
start_manager(Node, Vsns, Conf0, _Opts) ->
+
?DBG("start_manager -> entry with"
"~n Node: ~p"
"~n Vsns: ~p"
"~n Conf0: ~p"
"~n Opts: ~p", [Node, Vsns, Conf0, _Opts]),
-
+
AtlDir = ?config(manager_log_dir, Conf0),
ConfDir = ?config(manager_conf_dir, Conf0),
- DbDir = ?config(manager_db_dir, Conf0),
- IRB = ?config(irb, Conf0),
+ DbDir = ?config(manager_db_dir, Conf0),
+ IRB = ?config(irb, Conf0),
ConfigVerbosity = get_opt(manager_config_verbosity, Conf0, trace),
NoteStoreVerbosity = get_opt(manager_note_store_verbosity, Conf0, log),
@@ -6107,6 +6254,8 @@ start_manager(Node, Vsns, Conf0, _Opts) ->
AtlSeqNo = get_opt(manager_atl_seqno, Conf0, false),
+ CBP = get_opt(manager_server_cbproxy, Conf0, temporary),
+
NetIfConf =
case get_opt(manager_net_if_module, Conf0, no_module) of
no_module ->
@@ -6127,7 +6276,8 @@ start_manager(Node, Vsns, Conf0, _Opts) ->
{db_dir, DbDir},
{verbosity, ConfigVerbosity}]},
{note_store, [{verbosity, NoteStoreVerbosity}]},
- {server, [{verbosity, ServerVerbosity}]},
+ {server, [{verbosity, ServerVerbosity},
+ {cbproxy, CBP}]},
{net_if, NetIfConf}],
?line ok = set_mgr_env(Node, Env),
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index 290f1bc31a..4c57b42134 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -58,12 +58,69 @@ from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
from(_H, []) -> [].
+%% localhost() ->
+%% {ok, Ip} = snmp_misc:ip(net_adm:localhost()),
+%% Ip.
+%% localhost(Family) ->
+%% {ok, Ip} = snmp_misc:ip(net_adm:localhost(), Family),
+%% Ip.
+
localhost() ->
- {ok, Ip} = snmp_misc:ip(net_adm:localhost()),
- Ip.
+ localhost(inet).
+
localhost(Family) ->
- {ok, Ip} = snmp_misc:ip(net_adm:localhost(), Family),
- Ip.
+ case inet:getaddr(net_adm:localhost(), Family) of
+ {ok, {127, _, _, _}} when (Family =:= inet) ->
+ %% Ouch, we need to use something else
+ case inet:getifaddrs() of
+ {ok, IfList} ->
+ which_addr(Family, IfList);
+ {error, Reason1} ->
+ fail({getifaddrs, Reason1}, ?MODULE, ?LINE)
+ end;
+ {ok, {A1, _, _, _, _, _, _, _}} when (Family =:= inet6) andalso
+ ((A1 =:= 0) orelse
+ (A1 =:= 16#fe80)) ->
+ %% Ouch, we need to use something else
+ case inet:getifaddrs() of
+ {ok, IfList} ->
+ which_addr(Family, IfList);
+ {error, Reason1} ->
+ fail({getifaddrs, Reason1}, ?MODULE, ?LINE)
+ end;
+ {ok, Addr} ->
+ Addr;
+ {error, Reason2} ->
+ fail({getaddr, Reason2}, ?MODULE, ?LINE)
+ end.
+
+which_addr(_Family, []) ->
+ fail(no_valid_addr, ?MODULE, ?LINE);
+which_addr(Family, [{"lo", _} | IfList]) ->
+ which_addr(Family, IfList);
+which_addr(Family, [{"docker" ++ _, _} | IfList]) ->
+ which_addr(Family, IfList);
+which_addr(Family, [{"br-" ++ _, _} | IfList]) ->
+ which_addr(Family, IfList);
+which_addr(Family, [{_Name, IfOpts} | IfList]) ->
+ case which_addr2(Family, IfOpts) of
+ {ok, Addr} ->
+ Addr;
+ {error, _} ->
+ which_addr(Family, IfList)
+ end.
+
+which_addr2(_Family, []) ->
+ {error, not_found};
+which_addr2(Family, [{addr, Addr}|_])
+ when (Family =:= inet) andalso (size(Addr) =:= 4) ->
+ {ok, Addr};
+which_addr2(Family, [{addr, Addr}|_])
+ when (Family =:= inet6) andalso (size(Addr) =:= 8) ->
+ {ok, Addr};
+which_addr2(Family, [_|IfOpts]) ->
+ which_addr2(Family, IfOpts).
+
sz(L) when is_list(L) ->
length(L);