snmp_generic(3)
okay so bestie, this is the manual page for snmp_generic(3) β the Erlang module that's basically the backstage crew for your SNMP objects. It's giving "generic functions for implementing SNMP objects in a database" energy, and we're about to break it all the way down. π
β¨
β¨ NAME β¨
snmp_generic β Generic Functions for Implementing SNMP Objects in a Database
π DESCRIPTION π
So the module snmp_generic is packed with generic functions that let you implement tables (and variables, bestie, don't forget those) using the SNMP built-in database or Mnesia. These default functions get used when no instrumentation function is provided for a managed object in a MIB. But sometimes you gotta customize the default behavior, you know? Like when a trap should be sent if a row is deleted or modified, or when some hardware needs to be informed that information changed. It's giving "main character needs a custom touch" energy. π¦
The overall structure is shown in the following figure:
+---------------+
| SNMP Agent |
+- - - - - - - -+
| MIB |
+---------------+
|
Association file (associates a MIB object with
| snmp_generic:table_funct
| snmp_generic:variable_func)
+--------------------------------------+
| snmp_generic | Support for get-next,
| | RowStatus operations
+----------------------+---------------+
| snmpa_local_db | Mnesia | Database
+--------------+-------+---------------+
| dets | ets |
| (persistent) | |
+--------------+-------+
Each function takes the argument NameDb, which is a tuple {Name, Db}, to identify which database the functions should use. Name is the symbolic name of the managed object as defined in the MIB, and Db is either volatile, persistent, or mnesia. If it is mnesia, all variables are stored in the Mnesia table snmp_variables which must be a table with two attributes (not a Mnesia SNMP table). The SNMP tables are stored in Mnesia tables with the same names as the SNMP tables. All functions assume that a Mnesia table exists with the correct name and attributes. It is the programmer's responsibility to ensure this. Specifically, if variables are stored in Mnesia, the table snmp_variables must be created by the programmer. The record definition for this table is defined in the file snmp/include/snmp_types.hrl. No cap, that's just how it is. πΈ
If an instrumentation function in the association file for a variable myVar does not have a name when compiling an MIB, the compiler generates an entry.
{myVar, {snmp_generic, variable_func, [{myVar, Db]}}.
And for a table:
{myTable, {snmp_generic, table_func, [{myTable, Db]}}.
π Example π
The following example shows an implementation of a table which is stored in Mnesia, but with some checks performed at set-request operations. It's giving "custom logic but make it cute" vibes. β¨
myTable_func(new, NameDb) -> % pass unchanged
snmp_generic:table_func(new, NameDb).
myTable_func(delete, NameDb) -> % pass unchanged
snmp_generic:table_func(delete, NameDb).
%% change row
myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
case snmp_generic:table_func(is_set_ok, RowIndex,
Cols, NameDb) of
{noError, 0} ->
myApplication:is_set_ok(RowIndex, Cols);
Err ->
Err
end;
myTable_func(set, RowIndex, Cols, NameDb) ->
case snmp_generic:table_func(set, RowIndex, Cols,
NameDb),
{noError, 0} ->
% Now the row is updated, tell the application
myApplication:update(RowIndex, Cols);
Err ->
Err
end;
myTable_func(Op, RowIndex, Cols, NameDb) -> % pass unchanged
snmp_generic:table_func(Op, RowIndex, Cols, NameDb).
The .funcs file would look like:
{myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.
π DATA TYPES π
column() :: pos_integer().β a column, bestie. It's a positive integer, periodt.columns() :: [column()] | [{column(), Value :: term()}].β Is a list of column numbers in the case of a get operation, and a list of column numbers and values in the case of a set operation. So either just the column numbers, or the column numbers and their values. Slay. πtable_info_item() ::
nbr_of_cols | defvals | status_col | not_accessible |
index_types | first_accessible | first_own_index.
For an ordinary table, the types will be the following:
nbr_of_colsβ Number of columns. Value type:pos_integer()defvalsβ A list of default values, ordered by column. Value type:{Col :: [pos_integer(), DefVal :: term()]}status_colβ Column number of the status column. Value type:pos_integer()not_accessibleβ A sorted list of columns (>first_accessible) that are'not-accessible'. Value type:[pos_integer()]index_typesβ A list ofasn1_type()for the index columns, ordered by column number or an "augment"-tuple (see below). Value type:[asn1_type()]first_accessibleβ The first accessible column. Value type:pos_integer()first_own_indexβ Column number of the first own index. Will be0if there is no such index for this table. Value type:non_neg_integer()
For a augmented table, it will instead look like this:
index_typesβ Value type:{augments, {atom(), asn1_type()}}nbr_of_colsβ Value type:pos_integer()not_accessibleβ Value type:[pos_integer()]first_accessibleβ Value type:pos_integer()
π«Ά FUNCTIONS π«Ά
Okay bestie, this is the part where the good stuff lives β all the actual functions you can call. Buckle up. π
πΈ get_index_types(Name) -> IndexTypes
get_index_types(Name) -> IndexTypes
when
Name :: snmpa:name() | snmpa:name_db(),
IndexTypes :: [snmp:asn1_type()].
Gets the index types of Name. β¨
You'd use this inside instrumentation functions when you need to pull out the index types part of the table info. That's it, that's the whole vibe. π
πΈ get_status_col(Name, Cols) -> false | {value, StatusCol}
get_status_col(Name, Cols) -> false | {value, StatusCol}
when
Name :: snmpa:name() | snmpa:name_db(),
Cols :: columns(),
StatusCol :: term().
Gets the value of the status column straight out of Cols. π
Instrumentation functions love this one for is_set_ok, undo or set β it's how you check whether the status column of a table has been modified. Sneaky little status check, iconic honestly.
πΈ get_table_info(Name, Item) -> Result
get_table_info(Name, Item :: nbr_of_cols) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: pos_integer();
(Name, Item :: defvals) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: [{Col, DefVal}],
Col :: pos_integer(),
DefVal :: term();
(Name, Item :: status_col) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: pos_integer();
(Name, Item :: not_accessible) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: [pos_integer()];
(Name, Item :: index_types) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: [snmp:asn1_type()];
(Name, Item :: first_accessible) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: pos_integer();
(Name, Item :: first_own_index) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: non_neg_integer();
(Name, Item :: all) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: [{table_info_item(), term()}].
Grabs one specific table info item for you. π
But bestie β if Item is all? Then instead of one lil item you get back a two tuple list (a property list, iykyk) containing every item and its respective value for that table. The whole menu. π
Use this in instrumentation functions whenever you need to retrieve a given part of the table info.
πΈ table_func(Op, NameDb) -> Return
table_func(Op, NameDb) -> Return
when
Op :: new | delete,
NameDb :: snmpa:name_db(),
Return :: term().
This is the default instrumentation function for tables. π«Ά
- The
newoperation creates the table if it does not exist β but only if the database is the SNMP internal db. No cap. - The
deleteoperation does not delete the table from the database, since unloading an MIB does not necessarily mean that the table should be destroyed. Let that table live, honestly. π
If it's possible for a manager to create or delete rows in the table, there must be aRowStatuscolumn foris_set_ok,setandundoto work properly. Mandatory. Periodt.
The function returns according to the specification of an instrumentation function.
πΈ table_func(Op, RowIndex, Cols, NameDb) -> Return
table_func(Op, RowIndex, Cols, NameDb) -> Return
when
Op :: get | get_next | is_set_ok | set | undo,
RowIndex :: snmp:row_index(),
Cols :: columns(),
NameDb :: snmpa:name_db(),
Return :: term().
Still the default instrumentation function for tables, just the four-arg flavour. β¨
- The
is_set_okoperation checks that a row which is to be modified or deleted exists, and that a row which is to be created does not exist. Vibe check on the whole row situation. π₯ - The
undooperation does nothing. Truly the chillest operation. - The
setoperation checks if it has enough information to make the row change its status fromnotReadytonotInService(when a row has been set tocreateAndWait). If a row is set tocreateAndWait, columns without a value are set tonoinit. And if Mnesia is used, thesetfunctionality is handled within a transaction. π
Same warning, same energy: if a manager can create or delete rows in the table, there must be aRowStatuscolumn foris_set_ok,setandundoto work properly. π¨
The function returns according to the specification of an instrumentation function.
πΈ table_get_elements(NameDb, RowIndex, Cols) -> Values
table_get_elements(NameDb, RowIndex, Cols) -> Values
when
NameDb :: snmpa:name_db(),
RowIndex :: snmp:row_index(),
Cols :: columns(),
Values :: [noinit | Value],
Value :: term().
Returns a list with values for all the columns in Cols. π
If a column is undefined, its value is noinit. Simple as.
πΈ table_next(NameDb, RestOid) -> Result
table_next(NameDb, RestOid) -> Result
when
NameDb :: snmpa:name_db(),
RestOid :: [integer()],
Result :: RowIndex | endOfTable,
RowIndex :: snmp:row_index().
Finds the indices of the next row in the table. π
Cute detail: RestOid does not have to specify an existing row. It's giving "just point me somewhere, I'll figure it out". π¦
πΈ table_row_exists(NameDb, RowIndex) -> Result
table_row_exists(NameDb, RowIndex) -> Result
when
NameDb :: snmpa:name_db(),
RowIndex :: snmp:row_index(),
Result :: boolean().
Checks if a row in a table exists. That's it. Tiny function, huge main character energy. π
πΈ table_set_elements(NameDb, RowIndex, Columns) -> Result
table_set_elements(NameDb, RowIndex, Columns) -> Result
when
NameDb :: snmpa:name_db(),
RowIndex :: snmp:row_index(),
Columns :: [{Column, Value}],
Column :: column(),
Value :: term(),
Result :: boolean().
Sets the elements in Cols to the row specified by RowIndex. β‘
Ngl bestie: no checks are performed on the new values. It just does it. Live your truth, but know the risk. π
If the Mnesia database is used, this function calls mnesia:write to store the values. Which means this function must be called from within a transaction (mnesia:transaction/1). Don't forget, or it's not gonna slay. π
πΈ variable_func(Op, Name) -> Result
variable_func(Op :: new, Name) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: ok | boolean();
(Op :: delete, Name) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: ok;
(Op :: get, Name) -> Result
when
Name :: snmpa:name() | snmpa:name_db(),
Result :: {value, Value} | genErr,
Value :: term().
This is the default instrumentation function for variables. πΈ
- The
newoperation creates a new variable in the database with a default value as defined in the MIB, or a zero value (depending on the type). - The
deletefunction does not delete the variable from the database. Leaving it exactly where it is, respectfully. π
The function returns according to the specification of an instrumentation function.
πΈ variable_func(Op, Value, Name) -> Result
variable_func(Op :: is_set_ok, Value, Name) -> Result
when
Value :: term(),
Name :: snmpa:name() | snmpa:name_db(),
Result :: noError;
(Op :: set, Value, Name) -> Result
when
Value :: term(),
Name :: snmpa:name() | snmpa:name_db(),
Result :: noError | commitFailed;
(Op :: undo, Value, Name) -> Result
when
Value :: term(),
Name :: snmpa:name() | snmpa:name_db(),
Result :: noError.
Also the default instrumentation function for variables β but this is the one with operations: is_set_ok | set | undo. β¨
- The
is_set_okoperation does nothing. A legend of doing the absolute least. - The
setoperation returnsnoErrorif successful orcommitFailedotherwise. - The
undooperation does nothing. Again. Consistent queen. π
The function returns according to the specification of an instrumentation function.
πΈ variable_get(Name) -> {value, Value} | undefined
variable_get(Name) -> {value, Value} | undefined
when
Name :: snmpa:name() | snmpa:name_db(),
Value :: term().
Gets the value of a variable. Short, sweet, gets the job done. π«Ά
πΈ variable_set(Name, Value) -> boolean()
variable_set(Name, Value) -> boolean()
when
Name :: snmpa:name() | snmpa:name_db(),
Value :: term().
Sets a new value to a variable. π
The variable is created if it does not exist β no need to set up in advance, it'll show up. But ngl: no checks are made on the type of the new value. π³
Returns false if the NameDb argument is incorrectly specified, otherwise true.
π That's the whole page, bestie! Every single function, every arg, everynoinitand everycommitFailed, present and accounted for. You ate. π
β¨ Sign-off time β¨ β this page came from Ericsson AB, sitting pretty at snmp 5.20.5, and it's page snmp_generic(3). Go forth and instrument, my love. π¦ππΈ
π¦ where this page comes from
- ubuntu stonking: erlang-doc 1:29.0.6+dfsg-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms