diff options
author | Erlang/OTP <otp@erlang.org> | 2019-10-04 15:27:00 +0200 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2019-10-04 15:27:00 +0200 |
commit | 4d30fa161d5c59bb60a04585ecde657284c62fbd (patch) | |
tree | 6592c4e00ae0e930fc6fa85105892815dea00171 | |
parent | ab17b965bf2cd3d80d235b313e0756fc7f8bdf53 (diff) | |
parent | ddb3c60e5fc7e78b708042bca6a7d1775502d1c7 (diff) | |
download | erlang-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.xml | 25 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmp_config.xml | 23 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_config.erl | 37 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_mpd.erl | 16 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_server.erl | 412 | ||||
-rw-r--r-- | lib/snmp/test/snmp_manager_test.erl | 308 | ||||
-rw-r--r-- | lib/snmp/test/snmp_test_lib.erl | 65 |
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); |