summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2019-10-04 15:27:00 +0200
committerErlang/OTP <otp@erlang.org>2019-10-04 15:27:00 +0200
commit4d30fa161d5c59bb60a04585ecde657284c62fbd (patch)
tree6592c4e00ae0e930fc6fa85105892815dea00171
parentab17b965bf2cd3d80d235b313e0756fc7f8bdf53 (diff)
parentddb3c60e5fc7e78b708042bca6a7d1775502d1c7 (diff)
downloaderlang-4d30fa161d5c59bb60a04585ecde657284c62fbd.tar.gz
Merge branch 'bmk/snmp/manager/20190910/callback_proxy/OTP-15947' into maint-20
* bmk/snmp/manager/20190910/callback_proxy/OTP-15947: [snmp|manager|test] Adjusted the inform_swarm test case runtime [snmp|manager|doc] Document the new (cbproxy) option [snmp|manager|test] Add test cases using the new (cbproxy) feature [snmp|manager] Server callback proxy process config
-rw-r--r--lib/snmp/doc/src/snmp_app.xml25
-rw-r--r--lib/snmp/doc/src/snmp_config.xml23
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl37
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl16
-rw-r--r--lib/snmp/src/manager/snmpm_server.erl412
-rw-r--r--lib/snmp/test/snmp_manager_test.erl308
-rw-r--r--lib/snmp/test/snmp_test_lib.erl65
7 files changed, 713 insertions, 173 deletions
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index d5ac97ef15..2ae07601d4 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2019</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -582,7 +582,7 @@
<tag><marker id="manager_server"></marker>
<c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
- <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
+ <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
@@ -608,6 +608,27 @@
<p>Default is <c>30000</c>.</p>
</item>
+ <tag><marker id="manager_server_cbproxy"></marker>
+ <c><![CDATA[server_cbproxy() = temporary (default) | permanent <optional>]]></c></tag>
+ <item>
+ <p>This option specifies how the server will handle callback calls.</p>
+ <taglist>
+ <tag><marker id="manager_server_cbproxy_temporary"></marker>
+ <c><![CDATA[temporary (default)]]></c></tag>
+ <item>
+ <p>A temporary process will be created for each callback call. </p>
+ </item>
+
+ <tag><marker id="manager_server_cbproxy_temporary"></marker>
+ <c><![CDATA[permanent]]></c></tag>
+ <item>
+ <p>With this the server will create a permanent (named) process that
+ in effect serializes all callback calls.</p>
+ </item>
+ </taglist>
+ <p>Default is <c>temporary</c>.</p>
+ </item>
+
<tag><marker id="manager_config"></marker>
<c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index 6d4129dd06..6daa3ced21 100644
--- a/lib/snmp/doc/src/snmp_config.xml
+++ b/lib/snmp/doc/src/snmp_config.xml
@@ -611,7 +611,7 @@ in so far as it will be converted to the new format if found.
<tag><marker id="manager_server"></marker>
<c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
- <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
+ <p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()} | {cbproxy, server_cbproxy()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
@@ -637,6 +637,27 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>30000</c>.</p>
</item>
+ <tag><marker id="manager_server_cbproxy"></marker>
+ <c><![CDATA[server_cbproxy() = temporary (default) | permanent <optional>]]></c></tag>
+ <item>
+ <p>This option specifies how the server will handle callback calls.</p>
+ <taglist>
+ <tag><marker id="manager_server_cbproxy_temporary"></marker>
+ <c><![CDATA[temporary (default)]]></c></tag>
+ <item>
+ <p>A temporary process will be created for each callback call. </p>
+ </item>
+
+ <tag><marker id="manager_server_cbproxy_temporary"></marker>
+ <c><![CDATA[permanent]]></c></tag>
+ <item>
+ <p>With this the server will create a permanent (named) process that
+ in effect serializes all callback calls.</p>
+ </item>
+ </taglist>
+ <p>Default is <c>temporary</c>.</p>
+ </item>
+
<tag><marker id="manager_config"></marker>
<c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index 118cdcd1df..7711dacedf 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2019. 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.
@@ -147,7 +147,12 @@
-define(USER_MOD_DEFAULT, snmpm_user_default).
-define(USER_DATA_DEFAULT, undefined).
-%% -define(DEF_ADDR_TAG, default_addr_tag).
+-define(SERVER_OPT_VERB_DEFAULT, silence).
+-define(SERVER_OPT_GCT_DEFAULT, 30000).
+-define(SERVER_OPT_MT_DEFAULT, true).
+-define(SERVER_OPT_CBP_DEFAULT, temporary). % permanent
+
+%% -define(DEF_ADDR_TAG, default_addr_tag).
-define(DEFAULT_TARGETNAME, default_agent).
-define(DEF_PORT_TAG, default_port_tag).
-define(SUPPORTED_DOMAINS, [transportDomainUdpIpv4, transportDomainUdpIpv6]).
@@ -1117,12 +1122,14 @@ do_init(Opts) ->
%% -- Server (optional) --
ServerOpts = get_opt(server, Opts, []),
- ServerVerb = get_opt(verbosity, ServerOpts, silence),
- ServerGct = get_opt(timeout, ServerOpts, 30000),
- ServerMt = get_opt(multi_threaded, ServerOpts, true),
+ ServerVerb = get_opt(verbosity, ServerOpts, ?SERVER_OPT_VERB_DEFAULT),
+ ServerGct = get_opt(timeout, ServerOpts, ?SERVER_OPT_GCT_DEFAULT),
+ ServerMt = get_opt(multi_threaded, ServerOpts, ?SERVER_OPT_MT_DEFAULT),
+ ServerCBP = get_opt(cbproxy, ServerOpts, ?SERVER_OPT_CBP_DEFAULT),
ets:insert(snmpm_config_table, {server_verbosity, ServerVerb}),
ets:insert(snmpm_config_table, {server_timeout, ServerGct}),
ets:insert(snmpm_config_table, {server_multi_threaded, ServerMt}),
+ ets:insert(snmpm_config_table, {server_cbproxy, ServerCBP}),
%% -- Mibs (optional) --
?vdebug("initiate mini mib", []),
@@ -1415,6 +1422,11 @@ verify_server_opts([{verbosity, Verbosity}|Opts]) ->
verify_server_opts([{timeout, Timeout}|Opts]) ->
verify_server_timeout(Timeout),
verify_server_opts(Opts);
+verify_server_opts([{multi_threaded, MT}|Opts]) when is_boolean(MT) ->
+ verify_server_opts(Opts);
+verify_server_opts([{cbproxy, CBP}|Opts]) ->
+ verify_server_cbproxy(CBP),
+ verify_server_opts(Opts);
verify_server_opts([Opt|_]) ->
error({invalid_server_option, Opt}).
@@ -1423,6 +1435,13 @@ verify_server_timeout(T) when is_integer(T) andalso (T > 0) ->
verify_server_timeout(T) ->
error({invalid_server_timeout, T}).
+verify_server_cbproxy(temporary) ->
+ ok;
+verify_server_cbproxy(permanent) ->
+ ok;
+verify_server_cbproxy(CBP) ->
+ error({invalid_server_cbproxy, CBP}).
+
verify_net_if_opts([]) ->
ok;
verify_net_if_opts([{module, Mod}|Opts]) ->
@@ -1794,14 +1813,14 @@ order_agent(ItemA, ItemB) ->
snmp_conf:keyorder(1, ItemA, ItemB, [tdomain, port]).
fix_agent_config(Conf) ->
- ?vdebug("fix_agent_config -> entry with~n~n"
- " Conf: ~p", [Conf]),
+ ?vdebug("fix_agent_config -> entry with"
+ "~n Conf: ~p", [Conf]),
fix_agent_config(lists:sort(fun order_agent/2, Conf), []).
fix_agent_config([], FixedConf) ->
Ret = lists:reverse(FixedConf),
- ?vdebug("fix_agent_config -> returns:~n"
- " ~p", [Ret]),
+ ?vdebug("fix_agent_config -> done when (fixed config):"
+ "~n ~p", [Ret]),
Ret;
fix_agent_config([{taddress = Item, Address} = Entry|Conf], FixedConf) ->
{value, {tdomain, TDomain}} = lists:keysearch(tdomain, 1, FixedConf),
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 191dc2c281..89fb9005f9 100644
--- a/lib/snmp/src/manager/snmpm_mpd.erl
+++ b/lib/snmp/src/manager/snmpm_mpd.erl
@@ -869,8 +869,20 @@ get_agent_max_message_size(Domain, Addr) ->
{ok, MMS} ->
MMS;
_Error ->
- ?vlog("unknown agent: ~s",
- [snmp_conf:mk_addr_string({Domain, Addr})]),
+ TAddr = fun(TN) ->
+ case snmpm_config:agent_info(TN, taddress) of
+ {ok, TA} ->
+ TA;
+ {error, _} ->
+ undefined
+ end
+ end,
+ KnownAgents =
+ [{TargetName, TAddr(TargetName)} ||
+ TargetName <- snmpm_config:which_agents()],
+ ?vlog("[agent engine max msg size lookup] unknown agent: ~s"
+ "~n Known Agents: ~p",
+ [snmp_conf:mk_addr_string({Domain, Addr}), KnownAgents]),
get_max_message_size()
end.
%% get_agent_max_message_size(Addr, Port) ->
diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl
index c8d7fa1e8b..ea7091cf38 100644
--- a/lib/snmp/src/manager/snmpm_server.erl
+++ b/lib/snmp/src/manager/snmpm_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2019. 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.
@@ -77,6 +77,15 @@
%% GCT exports
-export([gct_init/1, gct/2]).
+%% CallBack Proxy exports
+-export([cbproxy_loop/1,
+ do_handle_error/4,
+ do_handle_pdu/5,
+ do_handle_agent/9,
+ do_handle_trap/9,
+ do_handle_inform/10,
+ do_handle_report/9]).
+
-include("snmpm_internal.hrl").
-include("snmp_debug.hrl").
@@ -134,6 +143,9 @@
-endif.
+-define(CBP_AWT_MAX, 60*60*1000*1000).
+-define(CBP_CNT_MAX, 16#FFFFFFFF).
+
%%----------------------------------------------------------------------
@@ -147,7 +159,16 @@
net_if_ref,
req, %% ???? Last request id in outgoing message
oid, %% ???? Last oid in request outgoing message
- mini_mib
+ mini_mib,
+ %% temporary: create a new (temporary) proxy process for each callback.
+ %% transient: create one proxy process per known agent
+ %% Its created "on the fly" and lives for as long as
+ %% there is activity (inactivity for a "long" time,
+ %% will cause it to terminate).
+ %% Not currently used!
+ %% permanent: create one (named) static callback proxy process.
+ cbproxy :: temporary | permanent,
+ cbproxy_pid % Pid of the callback proxy *if* cbp = permanent
}
).
@@ -183,6 +204,9 @@
).
+-define(CBPROXY, snmpm_server_cbproxy).
+
+
%%%-------------------------------------------------------------------
%%% API
%%%-------------------------------------------------------------------
@@ -544,6 +568,16 @@ do_init() ->
{ok, Timeout} = snmpm_config:system_info(server_timeout),
{ok, GCT} = gct_start(Timeout),
+ %% What kind of CallBack Proxy (temporary by default)
+ {CBProxy, CBPPid} =
+ case snmpm_config:system_info(server_cbproxy) of
+ {ok, permanent = CBP} ->
+ %% Start CallBack Proxy process
+ {CBP, cbproxy_start()};
+ {ok, CBP} ->
+ {CBP, undefined}
+ end,
+
%% -- Create request table --
ets:new(snmpm_request_table,
[set, protected, named_table, {keypos, #request.id}]),
@@ -553,7 +587,7 @@ do_init() ->
[set, protected, named_table, {keypos, #monitor.id}]),
%% -- Start the note-store and net-if processes --
- {NoteStore, NoteStoreRef} = do_init_note_store(Prio),
+ {NoteStore, NoteStoreRef} = do_init_note_store(Prio),
{NetIf, NetIfModule, NetIfRef} = do_init_net_if(NoteStore),
MiniMIB = snmpm_config:make_mini_mib(),
@@ -563,7 +597,9 @@ do_init() ->
note_store_ref = NoteStoreRef,
net_if = NetIf,
net_if_mod = NetIfModule,
- net_if_ref = NetIfRef},
+ net_if_ref = NetIfRef,
+ cbproxy = CBProxy,
+ cbproxy_pid = CBPPid},
?vlog("started", []),
{ok, State}.
@@ -1075,6 +1111,13 @@ handle_info({'EXIT', Pid, Reason}, #state{gct = Pid} = State) ->
{noreply, State#state{gct = GCT}};
+handle_info({'EXIT', Pid, Reason}, #state{cbproxy_pid = Pid} = State) ->
+ warning_msg("CallBack Proxy (~w) process crashed: "
+ "~n ~p", [Pid, Reason]),
+ NewCBP = cbproxy_start(),
+ {noreply, State#state{cbproxy_pid = NewCBP}};
+
+
handle_info(Info, State) ->
warning_msg("received unknown info: ~n~p", [Info]),
{noreply, State}.
@@ -1103,8 +1146,9 @@ code_change(_Vsn, #state{gct = Pid} = State0, _Extra) ->
%% Terminate
%%----------------------------------------------------------
-terminate(Reason, #state{gct = GCT}) ->
+terminate(Reason, #state{gct = GCT, cbproxy = CBP}) ->
?vdebug("terminate: ~p",[Reason]),
+ cbproxy_stop(CBP),
gct_stop(GCT),
snmpm_misc_sup:stop_note_store(),
snmpm_misc_sup:stop_net_if(),
@@ -1746,23 +1790,26 @@ handle_snmp_error(Domain, Addr, ReqId, Reason, State) ->
end.
-handle_error(_UserId, Mod, Reason, ReqId, Data, _State) ->
+handle_error(_UserId, Mod, Reason, ReqId, Data,
+ #state{cbproxy = CBP} = _State) ->
?vtrace("handle_error -> entry when"
"~n Mod: ~p", [Mod]),
- F = fun() ->
- try
- begin
- Mod:handle_error(ReqId, Reason, Data)
- end
- catch
- T:E ->
- CallbackArgs = [ReqId, Reason, Data],
- handle_invalid_result(handle_error, CallbackArgs, T, E)
- end
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_error,
+ [Mod, ReqId, Reason, Data]),
ok.
+do_handle_error(Mod, ReqId, Reason, Data) ->
+ try
+ begin
+ Mod:handle_error(ReqId, Reason, Data)
+ end
+ catch
+ C:E ->
+ CallbackArgs = [ReqId, Reason, Data],
+ handle_invalid_result(handle_error, CallbackArgs, C, E)
+ end.
+
handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu,
Domain, Addr, State) ->
@@ -1939,45 +1986,49 @@ handle_snmp_pdu(CrapPdu, Domain, Addr, _State) ->
handle_pdu(
_UserId, Mod, target_name = _RegType, TargetName, _Domain, _Addr,
- ReqId, SnmpResponse, Data, _State) ->
+ ReqId, SnmpResponse, Data, #state{cbproxy = CBP} = _State) ->
?vtrace("handle_pdu(target_name) -> entry when"
"~n Mod: ~p", [Mod]),
- F = fun() ->
- try
- begin
- Mod:handle_pdu(TargetName, ReqId, SnmpResponse, Data)
- end
- catch
- T:E ->
- CallbackArgs = [TargetName, ReqId, SnmpResponse, Data],
- handle_invalid_result(handle_pdu, CallbackArgs, T, E)
- end
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_pdu,
+ [Mod, TargetName, ReqId, SnmpResponse, Data]),
ok;
handle_pdu(
_UserId, Mod, addr_port = _RegType, _TargetName, _Domain, Addr,
- ReqId, SnmpResponse, Data, _State) ->
+ ReqId, SnmpResponse, Data, #state{cbproxy = CBP} = _State) ->
?vtrace("handle_pdu(addr_port) -> entry when"
"~n Mod: ~p", [Mod]),
- F = fun() ->
- {Ip, Port} = Addr,
- (catch Mod:handle_pdu(Ip, Port, ReqId, SnmpResponse, Data))
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_pdu,
+ [Mod, Addr, ReqId, SnmpResponse, Data]),
ok.
+do_handle_pdu(Mod, TargetName, ReqId, SnmpResponse, Data) ->
+ try
+ begin
+ Mod:handle_pdu(TargetName, ReqId, SnmpResponse, Data)
+ end
+ catch
+ C:E ->
+ CallbackArgs = [TargetName, ReqId, SnmpResponse, Data],
+ handle_invalid_result(handle_pdu, CallbackArgs, C, E)
+ end;
+do_handle_pdu(Mod, {Ip, Port}, ReqId, SnmpResponse, Data) ->
+ %% This is a deprecated version of the callback API, we skip handle
+ %% errors for this.
+ (catch Mod:handle_pdu(Ip, Port, ReqId, SnmpResponse, Data)).
+
-handle_agent(UserId, Mod, Domain, Addr, Type, Ref, SnmpInfo, Data, State) ->
+handle_agent(UserId, Mod, Domain, Addr, Type, Ref, SnmpInfo, Data,
+ #state{cbproxy = CBP} = State) ->
?vtrace("handle_agent -> entry when"
"~n UserId: ~p"
"~n Type: ~p"
"~n Mod: ~p", [UserId, Type, Mod]),
- F = fun() ->
- do_handle_agent(UserId, Mod, Domain, Addr,
- Type, Ref, SnmpInfo, Data, State)
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_agent,
+ [UserId, Mod, Domain, Addr,
+ Type, Ref, SnmpInfo, Data, State]),
ok.
do_handle_agent(DefUserId, DefMod,
@@ -2245,17 +2296,16 @@ do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) ->
handle_trap(
- UserId, Mod, RegType, Target, Domain, Addr, SnmpTrapInfo, Data, State) ->
+ UserId, Mod, RegType, Target, Domain, Addr, SnmpTrapInfo, Data,
+ #state{cbproxy = CBP} = State) ->
?vtrace("handle_trap -> entry with"
"~n UserId: ~p"
"~n Mod: ~p", [UserId, Mod]),
- F = fun() ->
- do_handle_trap(
- UserId, Mod,
- RegType, Target, Domain, Addr,
- SnmpTrapInfo, Data, State)
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_trap,
+ [UserId, Mod,
+ RegType, Target, Domain, Addr,
+ SnmpTrapInfo, Data, State]),
ok.
@@ -2423,17 +2473,16 @@ handle_snmp_inform(_Ref, CrapInform, Domain, Addr, _State) ->
handle_inform(
UserId, Mod, Ref,
- RegType, Target, Domain, Addr, SnmpInform, Data, State) ->
+ RegType, Target, Domain, Addr, SnmpInform, Data,
+ #state{cbproxy = CBP} = State) ->
?vtrace("handle_inform -> entry with"
"~n UserId: ~p"
"~n Mod: ~p", [UserId, Mod]),
- F = fun() ->
- do_handle_inform(
- UserId, Mod, Ref,
- RegType, Target, Domain, Addr, SnmpInform,
- Data, State)
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_inform,
+ [UserId, Mod, Ref,
+ RegType, Target, Domain, Addr, SnmpInform,
+ Data, State]),
ok.
do_handle_inform(
@@ -2746,16 +2795,15 @@ handle_snmp_report(CrapReqId, CrapReport, CrapInfo, Domain, Addr, _State) ->
handle_report(UserId, Mod, RegType, Target, Domain, Addr,
- SnmpReport, Data, State) ->
+ SnmpReport, Data,
+ #state{cbproxy = CBP} = State) ->
?vtrace("handle_report -> entry with"
"~n UserId: ~p"
"~n Mod: ~p", [UserId, Mod]),
- F = fun() ->
- do_handle_report(
- UserId, Mod, RegType, Target, Domain, Addr,
- SnmpReport, Data, State)
- end,
- handle_callback(F),
+ handle_callback(CBP,
+ do_handle_report,
+ [UserId, Mod, RegType, Target, Domain, Addr,
+ SnmpReport, Data, State]),
ok.
do_handle_report(
@@ -2844,17 +2892,217 @@ do_handle_report(
end.
-handle_callback(F) ->
+
+%%----------------------------------------------------------------------
+%% Handle Callback
+%%----------------------------------------------------------------------
+
+handle_callback(temporary, Func, Args) ->
V = get(verbosity),
erlang:spawn(
fun() ->
put(sname, msew),
put(verbosity, V),
- F()
- end).
+ apply(?MODULE, Func, Args)
+ end);
+%% handle_callback(transient, MFA) ->
+%% Pid = which_transient_callback_proxy(ProxyID),
+%% Pid ! {?MODULE, self(), {callback, MFA}};
+handle_callback(permanent, Func, Args) ->
+ case whereis(?CBPROXY) of
+ Pid when is_pid(Pid) ->
+ Pid ! {?MODULE, self(), {callback, {?MODULE, Func, Args}}};
+ _ ->
+ %% We should really either die or restart (the cbproxy).
+ %% It could also be a race, in which case spawning a temporary
+ %% process is better than nothing...
+ %% ...but we should inform someone...
+ warning_msg("Permanent Callback Proxy could not be found - "
+ "using temporary"),
+ handle_callback(temporary, Func, Args)
+ end.
+
+
+
+%%----------------------------------------------------------------------
+cbproxy_start() ->
+ cbproxy_start(infinity).
+
+cbproxy_start(IdleTimeout) ->
+ cbproxy_start(self(), IdleTimeout).
+
+cbproxy_start(Parent, IdleTimeout) ->
+ Pid = spawn_link(fun() -> cbproxy_init(Parent, IdleTimeout) end),
+ receive
+ {?MODULE, Pid, ready} ->
+ Pid
+ end.
+
+cbproxy_stop(permanent) ->
+ case whereis(?CBPROXY) of
+ Pid when is_pid(Pid) ->
+ Pid ! {?MODULE, self(), stop},
+ ok;
+ _ ->
+ ok
+ end;
+cbproxy_stop(_) ->
+ ok.
+
+cbproxy_info() ->
+ case whereis(?CBPROXY) of
+ Pid when is_pid(Pid) ->
+ Pid ! {?MODULE, self(), info},
+ receive
+ {?MODULE, Pid, {info, Info}} ->
+ Info
+ after 5000 ->
+ %% If a callback function takes a long time,
+ %% the cb proxy may be busy. But we only wait for
+ %% a "short" time. No point in making things
+ %% complicated when all we do is collecting "info".
+ [{timeout, process_info(Pid)}]
+ end;
+ _ ->
+ []
+ end.
+
+%% The timeout is future proofing (intended to be used for
+%% "when" we introduce a transient callback proxy).
+cbproxy_init(Parent, _IdleTimeout) ->
+ ?snmpm_info("CallBack Proxy: starting", []),
+ erlang:register(?CBPROXY, self()),
+ State = #{parent => Parent,
+ cnt => 0,
+ max_work => 0,
+ awork => 0},
+ Parent ! {?MODULE, self(), ready},
+ cbproxy_loop(State).
+
+%% * Every time a "counter" wraps, we send a message regarding this
+%% (to the server) and resets the counter.
+%% * Every time the AWT (accumulated work time) exceeds or is equal to 1h,
+%% we send a message regarding this (to the server) and resets the AWT.
+%%
+cbproxy_loop(#{parent := Pid} = State) ->
+ receive
+ {?MODULE, Pid, stop} ->
+ cbp_handle_stop(State),
+ exit(normal);
+
+
+ {?MODULE, Pid, info} ->
+ Info = cbp_handle_info(State),
+ Pid ! {?MODULE, self(), {info, Info}},
+ ?MODULE:cbproxy_loop(State);
+
+
+ %% And this is what we are here for:
+ {?MODULE, Pid, {callback, {Mod, Func, Args}}} ->
+ F = fun() -> apply(Mod, Func, Args) end,
+ ?MODULE:cbproxy_loop(cbp_handle_callback(State, F));
+
+ %% And this is what we are here for:
+ {?MODULE, Pid, {callback, F}} when is_function(F, 0) ->
+ ?MODULE:cbproxy_loop(cbp_handle_callback(State, F))
+
+
+ after 5000 ->
+ %% This is for code upgrade
+ ?MODULE:cbproxy_loop(State)
+ end.
+
+cbp_handle_stop(#{activity := AT,
+ cnt := CNT,
+ max_work := MWT,
+ awork := AWT}) ->
+ ?snmpm_info("CallBack Proxy: stop =>"
+ "~n Number of Calls: ~w"
+ "~n Last Activity: ~s"
+ "~n Max Work Time: ~s"
+ "~n Accumulated Work Time: ~s",
+ [CNT, cbp_fts(cbp_ts(AT)), cbp_ft(MWT), cbp_ft(AWT)]);
+cbp_handle_stop(_) ->
+ ?snmpm_info("CallBack Proxy: stop =>"
+ "~n Number of Calls: 0", []).
+
+cbp_handle_info(#{activity := AT,
+ cnt := CNT,
+ max_work := MWT,
+ awork := AWT}) ->
+ ATS = cbp_ts(AT),
+ [{cnt, CNT},
+ {activity, ATS},
+ {max_work, MWT},
+ {work, AWT}];
+cbp_handle_info(_) ->
+ [{cnt, 0}, {awork, 0}, {max_work, 0}].
+cbp_handle_callback(#{cnt := CNT1,
+ max_work := MWT,
+ awork := AWT1} = State, F) ->
+ T1 = cbp_t(),
+ (catch F()),
+ T2 = cbp_t(),
+ CallbackWT = T2 - T1,
+ NewMWT = cbp_max(CallbackWT, MWT),
+ AWT2 = cbp_inc(awt, AWT1, CallbackWT, ?CBP_AWT_MAX),
+ CNT2 = cbp_inc(cnt, CNT1, 1, ?CBP_CNT_MAX),
+ State#{cnt => CNT2,
+ max_work => NewMWT,
+ awork => AWT2,
+ activity => T2}.
+
+cbp_t() ->
+ erlang:system_time(microsecond).
+
+cbp_max(A, B) when (A > B) ->
+ A;
+cbp_max(_, B) ->
+ B.
+
+cbp_inc(awt, Val, Inc, Max) when (Val + Inc) > Max ->
+ ?snmpm_info("CallBack Proxy: Accumulated Work Time wrapped 1 hour", []),
+ (Val+Inc) - Max;
+cbp_inc(cnt, Val, Inc, Max) when (Val + Inc) > Max ->
+ ?snmpm_info("CallBack Proxy: work counter wrapped", []),
+ (Val+Inc) - Max;
+cbp_inc(_, Val, Inc, _) ->
+ Val + Inc.
+
+cbp_ts(T) ->
+ MegaSecs = T div 1000000000000,
+ Secs = T div 1000000 - MegaSecs*1000000,
+ MicroSecs = T rem 1000000,
+ {MegaSecs, Secs, MicroSecs}.
+
+cbp_fts({_, _, N3} = TS) ->
+ {Date, Time} = calendar:now_to_datetime(TS),
+ {YYYY,MM,DD} = Date,
+ {Hour,Min,Sec} = Time,
+ FormatDate =
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w ~w",
+ [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
+ lists:flatten(FormatDate).
+
+cbp_ft(T) when T < 1000 ->
+ cbp_f("~w usec", [T]);
+cbp_ft(T) when T < 1000000 ->
+ cbp_f("~w msec", [T div 1000]);
+cbp_ft(T) when T < 60000000 ->
+ cbp_f("~w sec", [T div (1000*1000)]);
+cbp_ft(T) ->
+ cbp_f("~w min", [T div (60*1000*1000)]).
+
+
+cbp_f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
+
+
+%%----------------------------------------------------------------------
+
handle_invalid_result(Func, Args, T, E) ->
Stacktrace = ?STACK(),
error_msg("Callback function failed: "
@@ -3410,6 +3658,8 @@ call(Req) ->
call(Req, To) ->
gen_server:call(?SERVER, Req, To).
+warning_msg(F) ->
+ warning_msg(F, []).
warning_msg(F, A) ->
?snmpm_warning("Server: " ++ F, A).
@@ -3419,23 +3669,33 @@ error_msg(F, A) ->
%%----------------------------------------------------------------------
-get_info(#state{gct = GCT,
- net_if = NI, net_if_mod = NIMod,
- note_store = NS}) ->
- Info = [{server, server_info(GCT)},
+get_info(#state{gct = GCT,
+ net_if = NI,
+ net_if_mod = NIMod,
+ note_store = NS,
+ cbproxy = CBP}) ->
+ Info = [{server, server_info(GCT, CBP)},
{config, config_info()},
{net_if, net_if_info(NI, NIMod)},
{note_store, note_store_info(NS)},
{stats_counters, get_stats_counters()}],
Info.
-server_info(GCT) ->
+server_info(GCT, CBP) ->
+ {CBPInfo, CBPSz} =
+ if
+ (CBP =:= permanent) ->
+ {[{cbp, cbproxy_info()}],
+ [{cbp, proc_mem(whereis(?CBPROXY))}]};
+ true ->
+ {[], []}
+ end,
ProcSize = proc_mem(self()),
GCTSz = proc_mem(GCT),
RTSz = tab_size(snmpm_request_table),
MTSz = tab_size(snmpm_monitor_table),
- [{process_memory, [{server, ProcSize}, {gct, GCTSz}]},
- {db_memory, [{request, RTSz}, {monitor, MTSz}]}].
+ [{process_memory, [{server, ProcSize}, {gct, GCTSz}] ++ CBPSz},
+ {db_memory, [{request, RTSz}, {monitor, MTSz}]}] ++ CBPInfo.
proc_mem(P) when is_pid(P) ->
case (catch erlang:process_info(P, memory)) of
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index bb9b05b89f..ce5d352c69 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 = 10000,
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);