<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css"> <title>Erlang -- Agent Implementation Example</title> </head> <body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript"> <!-- function getWinHeight() { var myHeight = 0; if( typeof( window.innerHeight ) == 'number' ) { //Non-IE myHeight = window.innerHeight; } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode' myHeight = document.documentElement.clientHeight; } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible myHeight = document.body.clientHeight; } return myHeight; } function setscrollpos() { var objf=document.getElementById('loadscrollpos'); document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; } function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', setscrollpos); //--></script><div id="leftnav"><div class="innertube"> <img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/snmp-4.22.1.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Simple Network Management Protocol (SNMP)</strong><br><strong>User's Guide</strong><br><small>Version 4.22.1</small></p> <br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p> <ul class="flipMenu" imagepath="../../../../doc/js/flipmenu"> <li id="no" title="SNMP Introduction" expanded="false">SNMP Introduction<ul> <li><a href="snmp_intro.html"> Top of chapter </a></li> <li title="Scope and Purpose"><a href="snmp_intro.html#id73205">Scope and Purpose</a></li> <li title="Prerequisites"><a href="snmp_intro.html#id63280">Prerequisites</a></li> <li title="Definitions"><a href="snmp_intro.html#id61217">Definitions</a></li> <li title="About This Manual"><a href="snmp_intro.html#id66265">About This Manual</a></li> <li title="Where to Find More Information"><a href="snmp_intro.html#id65242">Where to Find More Information</a></li> </ul> </li> <li id="no" title="Agent Functional Description" expanded="false">Agent Functional Description<ul> <li><a href="snmp_agent_funct_descr.html"> Top of chapter </a></li> <li title="Features"><a href="snmp_agent_funct_descr.html#id70043">Features</a></li> <li title="SNMPv1, SNMPv2 and SNMPv3"><a href="snmp_agent_funct_descr.html#id69677">SNMPv1, SNMPv2 and SNMPv3</a></li> <li title="Operation"><a href="snmp_agent_funct_descr.html#id71220">Operation</a></li> <li title="Sub-agents and MIB Loading"><a href="snmp_agent_funct_descr.html#id75292">Sub-agents and MIB Loading</a></li> <li title="Contexts and Communities"><a href="snmp_agent_funct_descr.html#id74241">Contexts and Communities</a></li> <li title="Management of the Agent"><a href="snmp_agent_funct_descr.html#id74376">Management of the Agent</a></li> <li title="Notifications"><a href="snmp_agent_funct_descr.html#id73838">Notifications</a></li> <li title="Discovery"><a href="snmp_agent_funct_descr.html#id75718">Discovery</a></li> </ul> </li> <li id="no" title="Manager Functional Description" expanded="false">Manager Functional Description<ul> <li><a href="snmp_manager_funct_descr.html"> Top of chapter </a></li> <li title="Features"><a href="snmp_manager_funct_descr.html#id75862">Features</a></li> <li title="Operation"><a href="snmp_manager_funct_descr.html#id76012">Operation</a></li> <li title="MIB loading"><a href="snmp_manager_funct_descr.html#id76080">MIB loading</a></li> </ul> </li> <li id="no" title="The MIB Compiler" expanded="false">The MIB Compiler<ul> <li><a href="snmp_mib_compiler.html"> Top of chapter </a></li> <li title="Operation"><a href="snmp_mib_compiler.html#id76200">Operation</a></li> <li title="Importing MIBs"><a href="snmp_mib_compiler.html#id76263">Importing MIBs</a></li> <li title="MIB Consistency Checking"><a href="snmp_mib_compiler.html#id76334">MIB Consistency Checking</a></li> <li title=".hrl File Generation"><a href="snmp_mib_compiler.html#id76371">.hrl File Generation</a></li> <li title="Emacs Integration"><a href="snmp_mib_compiler.html#id76421">Emacs Integration</a></li> <li title="Compiling from a Shell or a Makefile"><a href="snmp_mib_compiler.html#id76467">Compiling from a Shell or a Makefile</a></li> <li title="Deviations from the Standard"><a href="snmp_mib_compiler.html#id76521">Deviations from the Standard</a></li> </ul> </li> <li id="no" title="Running the application" expanded="false">Running the application<ul> <li><a href="snmp_config.html"> Top of chapter </a></li> <li title="Configuring the application"><a href="snmp_config.html#id76778">Configuring the application</a></li> <li title="Modifying the Configuration Files"><a href="snmp_config.html#id79236">Modifying the Configuration Files</a></li> <li title="Starting the application"><a href="snmp_config.html#id79327">Starting the application</a></li> <li title="Debugging the application"><a href="snmp_config.html#id79377">Debugging the application</a></li> </ul> </li> <li id="no" title="Definition of Agent Configuration Files" expanded="false">Definition of Agent Configuration Files<ul> <li><a href="snmp_agent_config_files.html"> Top of chapter </a></li> <li title="Agent Information"><a href="snmp_agent_config_files.html#id79867">Agent Information</a></li> <li title="Contexts"><a href="snmp_agent_config_files.html#id79944">Contexts</a></li> <li title="System Information"><a href="snmp_agent_config_files.html#id79997">System Information</a></li> <li title="Communities"><a href="snmp_agent_config_files.html#id80066">Communities</a></li> <li title="MIB Views for VACM"><a href="snmp_agent_config_files.html#id80148">MIB Views for VACM</a></li> <li title="Security data for USM"><a href="snmp_agent_config_files.html#id80387">Security data for USM</a></li> <li title="Notify Definitions"><a href="snmp_agent_config_files.html#id80603">Notify Definitions</a></li> <li title="Target Address Definitions"><a href="snmp_agent_config_files.html#id80684">Target Address Definitions</a></li> <li title="Target Parameters Definitions"><a href="snmp_agent_config_files.html#id80890">Target Parameters Definitions</a></li> </ul> </li> <li id="no" title="Definition of Manager Configuration Files" expanded="false">Definition of Manager Configuration Files<ul> <li><a href="snmp_manager_config_files.html"> Top of chapter </a></li> <li title="Manager Information"><a href="snmp_manager_config_files.html#id81118">Manager Information</a></li> <li title="Users"><a href="snmp_manager_config_files.html#id81260">Users</a></li> <li title="Agents"><a href="snmp_manager_config_files.html#id81361">Agents</a></li> <li title="Security data for USM"><a href="snmp_manager_config_files.html#id81544">Security data for USM</a></li> </ul> </li> <li id="loadscrollpos" title="Agent Implementation Example" expanded="true">Agent Implementation Example<ul> <li><a href="snmp_impl_example_agent.html"> Top of chapter </a></li> <li title="MIB"><a href="snmp_impl_example_agent.html#id81793">MIB</a></li> <li title="Default Implementation"><a href="snmp_impl_example_agent.html#id81833">Default Implementation</a></li> <li title="Manual Implementation"><a href="snmp_impl_example_agent.html#id81912">Manual Implementation</a></li> </ul> </li> <li id="no" title="Manager Implementation Example" expanded="false">Manager Implementation Example<ul> <li><a href="snmp_impl_example_manager.html"> Top of chapter </a></li> <li title="The example manager"><a href="snmp_impl_example_manager.html#id82242">The example manager</a></li> <li title="A simple standard test"><a href="snmp_impl_example_manager.html#id82333">A simple standard test</a></li> </ul> </li> <li id="no" title="Instrumentation Functions" expanded="false">Instrumentation Functions<ul> <li><a href="snmp_instr_functions.html"> Top of chapter </a></li> <li title="Instrumentation Functions"><a href="snmp_instr_functions.html#id82473">Instrumentation Functions</a></li> <li title="Using the ExtraArgument"><a href="snmp_instr_functions.html#id83088">Using the ExtraArgument</a></li> <li title="Default Instrumentation"><a href="snmp_instr_functions.html#id83196">Default Instrumentation</a></li> <li title="Atomic Set"><a href="snmp_instr_functions.html#id83301">Atomic Set</a></li> </ul> </li> <li id="no" title="Definition of Instrumentation Functions" expanded="false">Definition of Instrumentation Functions<ul> <li><a href="snmp_def_instr_functions.html"> Top of chapter </a></li> <li title="Variable Instrumentation"><a href="snmp_def_instr_functions.html#id83474">Variable Instrumentation</a></li> <li title="Table Instrumentation"><a href="snmp_def_instr_functions.html#id83849">Table Instrumentation</a></li> </ul> </li> <li id="no" title="Definition of Agent Net if" expanded="false">Definition of Agent Net if<ul> <li><a href="snmp_agent_netif.html"> Top of chapter </a></li> <li title="Mandatory Functions"><a href="snmp_agent_netif.html#id84750">Mandatory Functions</a></li> <li title="Messages"><a href="snmp_agent_netif.html#id84772">Messages</a></li> </ul> </li> <li id="no" title="Definition of Manager Net if" expanded="false">Definition of Manager Net if<ul> <li><a href="snmp_manager_netif.html"> Top of chapter </a></li> <li title="Mandatory Functions"><a href="snmp_manager_netif.html#id85574">Mandatory Functions</a></li> <li title="Messages"><a href="snmp_manager_netif.html#id85591">Messages</a></li> </ul> </li> <li id="no" title="Audit Trail Log" expanded="false">Audit Trail Log<ul> <li><a href="snmp_audit_trail_log.html"> Top of chapter </a></li> <li title="Agent Logging"><a href="snmp_audit_trail_log.html#id85997">Agent Logging</a></li> <li title="Manager Logging"><a href="snmp_audit_trail_log.html#id86040">Manager Logging</a></li> </ul> </li> <li id="no" title="Advanced Agent Topics" expanded="false">Advanced Agent Topics<ul> <li><a href="snmp_advanced_agent.html"> Top of chapter </a></li> <li title="When to use a Sub-agent"><a href="snmp_advanced_agent.html#id86186">When to use a Sub-agent</a></li> <li title="Agent Semantics"><a href="snmp_advanced_agent.html#id86296">Agent Semantics</a></li> <li title="Sub-agents and Dependencies "><a href="snmp_advanced_agent.html#id86360">Sub-agents and Dependencies </a></li> <li title="Distributed Tables"><a href="snmp_advanced_agent.html#id86378">Distributed Tables</a></li> <li title="Fault Tolerance"><a href="snmp_advanced_agent.html#id86434">Fault Tolerance</a></li> <li title="Using Mnesia Tables as SNMP Tables"><a href="snmp_advanced_agent.html#id86508">Using Mnesia Tables as SNMP Tables</a></li> <li title="Deviations from the Standard"><a href="snmp_advanced_agent.html#id86786">Deviations from the Standard</a></li> </ul> </li> <li id="no" title="SNMP Appendix A" expanded="false">SNMP Appendix A<ul> <li><a href="snmp_app_a.html"> Top of chapter </a></li> <li title="Appendix A"><a href="snmp_app_a.html#id86932">Appendix A</a></li> </ul> </li> <li id="no" title="SNMP Appendix B" expanded="false">SNMP Appendix B<ul> <li><a href="snmp_app_b.html"> Top of chapter </a></li> <li title="Appendix B"><a href="snmp_app_b.html#id87320">Appendix B</a></li> </ul> </li> </ul> </div></div> <div id="content"> <div class="innertube"> <h1>8 Agent Implementation Example</h1> <p>This <strong>Implementation Example</strong> section describes how an MIB can be implemented with the SNMP Development Toolkit. </p> <p>The example shown can be found in the toolkit distribution. </p> <p>The agent is configured with the configuration tool, using default suggestions for everything but the manager node. </p> <h3><a name="id81793">8.1 MIB</a></h3> <p>The MIB used in this example is called EX1-MIB. It contains two objects, a variable with a name and a table with friends. </p> <div class="example"><pre> EX1-MIB DEFINITIONS ::= BEGIN IMPORTS RowStatus FROM STANDARD-MIB DisplayString FROM RFC1213-MIB OBJECT-TYPE FROM RFC-1212 ; example1 OBJECT IDENTIFIER ::= { experimental 7 } myName OBJECT-TYPE SYNTAX DisplayString (SIZE (0..255)) ACCESS read-write STATUS mandatory DESCRIPTION "My own name" ::= { example1 1 } friendsTable OBJECT-TYPE SYNTAX SEQUENCE OF FriendsEntry ACCESS not-accessible STATUS mandatory DESCRIPTION "A list of friends." ::= { example1 4 } friendsEntry OBJECT-TYPE SYNTAX FriendsEntry ACCESS not-accessible STATUS mandatory DESCRIPTION "" INDEX { fIndex } ::= { friendsTable 1 } FriendsEntry ::= SEQUENCE { fIndex INTEGER, fName DisplayString, fAddress DisplayString, fStatus RowStatus } fIndex OBJECT-TYPE SYNTAX INTEGER ACCESS not-accessible STATUS mandatory DESCRIPTION "number of friend" ::= { friendsEntry 1 } fName OBJECT-TYPE SYNTAX DisplayString (SIZE (0..255)) ACCESS read-write STATUS mandatory DESCRIPTION "Name of friend" ::= { friendsEntry 2 } fAddress OBJECT-TYPE SYNTAX DisplayString (SIZE (0..255)) ACCESS read-write STATUS mandatory DESCRIPTION "Address of friend" ::= { friendsEntry 3 } fStatus OBJECT-TYPE SYNTAX RowStatus ACCESS read-write STATUS mandatory DESCRIPTION "The status of this conceptual row." ::= { friendsEntry 4 } fTrap TRAP-TYPE ENTERPRISE example1 VARIABLES { myName, fIndex } DESCRIPTION "This trap is sent when something happens to the friend specified by fIndex." ::= 1 END </pre></div> <h3><a name="id81833">8.2 Default Implementation</a></h3> <p>Without writing any instrumentation functions, we can compile the MIB and use the default implementation of it. Recall that MIBs imported by "EX1-MIB.mib" must be present and compiled in the current directory ("./STANDARD-MIB.bin","./RFC1213-MIB.bin") when compiling. </p> <div class="example"><pre> unix> <span class="bold_code">erl -config ./sys</span> 1> <span class="bold_code">application:start(snmp).</span> ok 2> <span class="bold_code">snmpc:compile("EX1-MIB").</span> No accessfunction for 'friendsTable', using default. No accessfunction for 'myName', using default. {ok, "EX1-MIB.bin"} 3> <span class="bold_code">snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).</span> ok </pre></div> <p>This MIB is now loaded into the agent, and a manager can ask questions. As an example of this, we start another Erlang system and the simple Erlang manager in the toolkit: </p> <div class="example"><pre> 1> <span class="bold_code">snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},</span> %% making it understand symbolic names: {mibs,["EX1-MIB","STANDARD-MIB"]}]). {ok, <0.89.0>} %% a get-next request with one OID. 2> <span class="bold_code">snmp_test_mgr:gn([[1,3,6,1,3,7]]).</span> ok * Got PDU: [myName,0] = [] %% A set-request (now using symbolic names for convenience) 3> <span class="bold_code">snmp_test_mgr:s([{[myName,0], "Martin"}]).</span> ok * Got PDU: [myName,0] = "Martin" %% Try the same get-next request again 4> <span class="bold_code">snmp_test_mgr:gn([[1,3,6,1,3,7]]).</span> ok * Got PDU: [myName,0] = "Martin" %% ... and we got the new value. %% you can event do row operations. How to add a row: 5> <span class="bold_code">snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).</span> %% createAndGo ok * Got PDU: [fName,0] = "Martin" [fAddress,0] = "home" [fStatus,0] = 4 6> <span class="bold_code">snmp_test_mgr:gn([[myName,0]]).</span> ok * Got PDU: [fName,0] = "Martin" 7> <span class="bold_code">snmp_test_mgr:gn().</span> ok * Got PDU: [fAddress,0] = "home" 8> <span class="bold_code">snmp_test_mgr:gn().</span> ok * Got PDU: [fStatus,0] = 1 9> </pre></div> <h3><a name="id81912">8.3 Manual Implementation</a></h3> <p>The following example shows a "manual" implementation of the EX1-MIB in Erlang. In this example, the values of the objects are stored in an Erlang server. The server has a 2-tuple as loop data, where the first element is the value of variable <span class="code">myName</span>, and the second is a sorted list of rows in the table <span class="code">friendsTable</span>. Each row is a 4-tuple. </p> <div class="note"> <div class="label">Note</div> <div class="content"><p> <p>There are more efficient ways to create tables manually, i.e. to use the module <span class="code">snmp_index</span>.</p> </p></div> </div> <h4>Code</h4> <div class="example"><pre> -module(ex1). -author('dummy@flop.org'). %% External exports -export([start/0, my_name/1, my_name/2, friends_table/3]). %% Internal exports -export([init/0]). -define(status_col, 4). -define(active, 1). -define(notInService, 2). -define(notReady, 3). -define(createAndGo, 4). % Action; written, not read -define(createAndWait, 5). % Action; written, not read -define(destroy, 6). % Action; written, not read start() -> spawn(ex1, init, []). %%---------------------------------------------------------------- %% Instrumentation function for variable myName. %% Returns: (get) {value, Name} %% (set) noError %%---------------------------------------------------------------- my_name(get) -> ex1_server ! {self(), get_my_name}, Name = wait_answer(), {value, Name}. my_name(set, NewName) -> ex1_server ! {self(), {set_my_name, NewName}}, noError. %%---------------------------------------------------------------- %% Instrumentation function for table friendsTable. %%---------------------------------------------------------------- friends_table(get, RowIndex, Cols) -> case get_row(RowIndex) of {ok, Row} -> get_cols(Cols, Row); _ -> {noValue, noSuchInstance} end; friends_table(get_next, RowIndex, Cols) -> case get_next_row(RowIndex) of {ok, Row} -> get_next_cols(Cols, Row); _ -> case get_next_row([]) of {ok, Row} -> % Get next cols from first row. NewCols = add_one_to_cols(Cols), get_next_cols(NewCols, Row); _ -> end_of_table(Cols) end end; %%---------------------------------------------------------------- %% If RowStatus is set, then: %% *) If set to destroy, check that row does exist %% *) If set to createAndGo, check that row does not exist AND %% that all columns are given values. %% *) Otherwise, error (for simplicity). %% Otherwise, row is modified; check that row exists. %%---------------------------------------------------------------- friends_table(is_set_ok, RowIndex, Cols) -> RowExists = case get_row(RowIndex) of {ok, _Row} -> true; _ -> false end, case is_row_status_col_changed(Cols) of {true, ?destroy} when RowExists == true -> {noError, 0}; {true, ?createAndGo} when RowExists == false, length(Cols) == 3 -> {noError, 0}; {true, _} -> {inconsistentValue, ?status_col}; false when RowExists == true -> {noError, 0}; _ -> [{Col, _NewVal} | _Cols] = Cols, {inconsistentName, Col} end; friends_table(set, RowIndex, Cols) -> case is_row_status_col_changed(Cols) of {true, ?destroy} -> ex1_server ! {self(), {delete_row, RowIndex}}; {true, ?createAndGo} -> NewRow = make_row(RowIndex, Cols), ex1_server ! {self(), {add_row, NewRow}}; false -> {ok, Row} = get_row(RowIndex), NewRow = merge_rows(Row, Cols), ex1_server ! {self(), {delete_row, RowIndex}}, ex1_server ! {self(), {add_row, NewRow}} end, {noError, 0}. %%---------------------------------------------------------------- %% Make a list of {value, Val} of the Row and Cols list. %%---------------------------------------------------------------- get_cols([Col | Cols], Row) -> [{value, element(Col, Row)} | get_cols(Cols, Row)]; get_cols([], _Row) -> []. %%---------------------------------------------------------------- %% As get_cols, but the Cols list may contain invalid column %% numbers. If it does, we must find the next valid column, %% or return endOfTable. %%---------------------------------------------------------------- get_next_cols([Col | Cols], Row) when Col < 2 -> [{[2, element(1, Row)], element(2, Row)} | get_next_cols(Cols, Row)]; get_next_cols([Col | Cols], Row) when Col > 4 -> [endOfTable | get_next_cols(Cols, Row)]; get_next_cols([Col | Cols], Row) -> [{[Col, element(1, Row)], element(Col, Row)} | get_next_cols(Cols, Row)]; get_next_cols([], _Row) -> []. %%---------------------------------------------------------------- %% Make a list of endOfTable with as many elems as Cols list. %%---------------------------------------------------------------- end_of_table([Col | Cols]) -> [endOfTable | end_of_table(Cols)]; end_of_table([]) -> []. add_one_to_cols([Col | Cols]) -> [Col + 1 | add_one_to_cols(Cols)]; add_one_to_cols([]) -> []. is_row_status_col_changed(Cols) -> case lists:keysearch(?status_col, 1, Cols) of {value, {?status_col, StatusVal}} -> {true, StatusVal}; _ -> false end. get_row(RowIndex) -> ex1_server ! {self(), {get_row, RowIndex}}, wait_answer(). get_next_row(RowIndex) -> ex1_server ! {self(), {get_next_row, RowIndex}}, wait_answer(). wait_answer() -> receive {ex1_server, Answer} -> Answer end. %%%--------------------------------------------------------------- %%% Server code follows %%%--------------------------------------------------------------- init() -> register(ex1_server, self()), loop("", []). loop(MyName, Table) -> receive {From, get_my_name} -> From ! {ex1_server, MyName}, loop(MyName, Table); {From, {set_my_name, NewName}} -> loop(NewName, Table); {From, {get_row, RowIndex}} -> Res = table_get_row(Table, RowIndex), From ! {ex1_server, Res}, loop(MyName, Table); {From, {get_next_row, RowIndex}} -> Res = table_get_next_row(Table, RowIndex), From ! {ex1_server, Res}, loop(MyName, Table); {From, {delete_row, RowIndex}} -> NewTable = table_delete_row(Table, RowIndex), loop(MyName, NewTable); {From, {add_row, NewRow}} -> NewTable = table_add_row(Table, NewRow), loop(MyName, NewTable) end. %%%--------------------------------------------------------------- %%% Functions for table operations. The table is represented as %%% a list of rows. %%%--------------------------------------------------------------- table_get_row([{Index, Name, Address, Status} | _], [Index]) -> {ok, {Index, Name, Address, Status}}; table_get_row([H | T], RowIndex) -> table_get_row(T, RowIndex); table_get_row([], _RowIndex) -> no_such_row. table_get_next_row([Row | T], []) -> {ok, Row}; table_get_next_row([Row | T], [Index | _]) when element(1, Row) > Index -> {ok, Row}; table_get_next_row([Row | T], RowIndex) -> table_get_next_row(T, RowIndex); table_get_next_row([], RowIndex) -> endOfTable. table_delete_row([{Index, _, _, _} | T], [Index]) -> T; table_delete_row([H | T], RowIndex) -> [H | table_delete_row(T, RowIndex)]; table_delete_row([], _RowIndex) -> []. table_add_row([Row | T], NewRow) when element(1, Row) > element(1, NewRow) -> [NewRow, Row | T]; table_add_row([H | T], NewRow) -> [H | table_add_row(T, NewRow)]; table_add_row([], NewRow) -> [NewRow]. make_row([Index], [{2, Name}, {3, Address} | _]) -> {Index, Name, Address, ?active}. merge_rows(Row, [{Col, NewVal} | T]) -> merge_rows(setelement(Col, Row, NewVal), T); merge_rows(Row, []) -> Row. </pre></div> <h4>Association File</h4> <p>The association file <span class="code">EX1-MIB.funcs</span> for the real implementation looks as follows: </p> <div class="example"><pre> {myName, {ex1, my_name, []}}. {friendsTable, {ex1, friends_table, []}}. </pre></div> <h4>Transcript</h4> <p>To use the real implementation, we must recompile the MIB and load it into the agent. </p> <div class="example"><pre> 1> <span class="bold_code">application:start(snmp).</span> ok 2> <span class="bold_code">snmpc:compile("EX1-MIB").</span> {ok,"EX1-MIB.bin"} 3> <span class="bold_code">snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).</span> ok 4> <span class="bold_code">ex1:start().</span> <0.115.0> %% Now all requests operates on this "real" implementation. %% The output from the manager requests will *look* exactly the %% same as for the default implementation. </pre></div> <h4>Trap Sending</h4> <p>How to send a trap by sending the <span class="code">fTrap</span> from the master agent is shown in this section. The master agent has the MIB <span class="code">EX1-MIB</span> loaded, where the trap is defined. This trap specifies that two variables should be sent along with the trap, <span class="code">myName</span> and <span class="code">fIndex</span>. <span class="code">fIndex</span> is a table column, so we must provide its value and the index for the row in the call to <span class="code">snmpa:send_trap/4</span>. In the example below, we assume that the row in question is indexed by 2 (the row with <span class="code">fIndex</span> 2). </p> <p>we use a simple Erlang SNMP manager, which can receive traps. </p> <div class="example"><pre> [MANAGER] 1> <span class="bold_code">snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"public"}</span> %% does not have write-access 1><span class="bold_code">{mibs,["EX1-MIB","STANDARD-MIB"]}]).</span> {ok, <0.100.0>} 2> <span class="bold_code">snmp_test_mgr:s([{[myName,0], "Klas"}]).</span> ok * Got PDU: Received a trap: Generic: 4 %% authenticationFailure Enterprise: [iso,2,3] Specific: 0 Agent addr: [123,12,12,21] TimeStamp: 42993 2> [AGENT] 3> <span class="bold_code">snmpa:send_trap(snmp_master_agent, fTrap,"standard trap", [{fIndex,[2],2}]).</span> [MANAGER] 2> * Got PDU: Received a trap: Generic: 6 Enterprise: [example1] Specific: 1 Agent addr: [123,12,12,21] TimeStamp: 69649 [myName,0] = "Martin" [fIndex,2] = 2 2> </pre></div> </div> <div class="footer"> <hr> <p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>