snmp_index(3)

πŸ“¦
version 29.0.6 Β· 3 versions
, in ubuntu stonking

snmp_index πŸ’–

okay so bestie, this is snmp_index, straight out of the Erlang module definitions (manual section 3, iykyk). it's the iconic little ADT that makes SNMP tables behave, and we're gonna go through every single bit of it together. grab a snack πŸ“


✨ NAME ✨

snmp_index β€” Abstract Data Type for SNMP Indexing. that's it, that's the whole vibe. πŸ‘‘


🌸 DESCRIPTION 🌸

okay so the module snmp_index implements an Abstract Data Type (ADT) for an SNMP index structure for SNMP tables. it's implemented as an ets table of the ordered_set data-type, which means β€” and I need you to hear this β€” every single operation is O(log n). we LOVE a logarithmic queen. πŸ’…

in the table, the key is an ASN.1 OBJECT IDENTIFIER.

this index exists to keep the SNMP ordering implementation separate from the actual implementation of the table. the SNMP ordering, like, the implementation of GET NEXT, is what lives in this module.

so, example time bestie. suppose there's an SNMP table that's best implemented in Erlang as one process per SNMP table row. suppose further that the INDEX in the SNMP table is an OCTET STRING. the index structure would be created like this:

snmp_index:new(string)

and then for each new process we create, we insert an item into an snmp_index structure:

new_process(Name, SnmpIndex) ->
  Pid = start_process(),
  NewSnmpIndex =
    snmp_index:insert(SnmpIndex, Name, Pid),
  <...>

with this structure, we can now map an OBJECT IDENTIFIER in, say, a GET NEXT request, to the correct process:

get_next_pid(Oid, SnmpIndex) ->
  {ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
  Pid.

okay that's genuinely so clean it's giving main character energy. 🌈


🚨 Warnings 🚨

WARNING: every single API function that updates the index returns a NewIndex term. this is for backward compatibility with a previous implementation that used a B+ tree written purely in Erlang for the index. the NewIndex return value can now be ignored β€” it's literally just the unchanged table identifier for the ets table now.

ngl, the ets table implementation introduces a semantic incompatibility with older implementations, so listen up. in those older implementations, using pure Erlang terms, the index was garbage collected like any other Erlang term and did not have to be deleted when discarded. but an ets table is deleted only when the process creating it explicitly deletes it, or when the creating process terminates. 😭

so a new interface delete/1 was added to handle the case where a process wants to discard an index table (i.e. to build a completely new one). any application using transient snmp indexes has to be modified to handle this. as an snmp adaption usually keeps the index for the whole of the system's lifetime, this is rarely a problem. phew. 🫢


πŸ¦‹ DATA TYPES πŸ¦‹

  • -opaque index() β€” this type denotes an snmp index structure.
  • key() :: key_spec() | tuple(). β€” this type correlates to the key_types/0 type. if the key_types/0 is a single atom, the corresponding key/0 is a single type as well, but if the key_types/0 is a tuple, key/0 must be a tuple of the same size.

in the example above, valid keys could be {"hi", "mom"} and {"no", "thanks"}, whereas "hi", {"hi", 42} and {"hello", "there"} would be invalid. πŸ™ˆ

there is no way to properly describe this type in the erlang type language, which is why tuple/0 was used above. the proper definition looks like:

key() = key_spec() | {key_spec(), key_spec(), ...}
  • key_spec() :: string() | integer().
  • key_types() :: type_spec() | tuple(). β€” this type is used when creating the index structure, and the key/0 type is used when inserting and deleting items from the structure.

if the INDEX column is of type INTEGER, or derived from INTEGER, the corresponding type should be integer. if it's a variable length type (e.g. OBJECT IDENTIFIER, OCTET STRING), the corresponding type should be string. finally, if the type is of variable length, but with a fixed size restriction (e.g. IpAddress), the corresponding type should be fix_string. πŸ’…

there is no way to properly describe this type in the erlang type language, which is why tuple/0 was used above. the proper definition looks like:

key_types = type_spec() | {type_spec(), type_spec(), ...}
  • type_spec() :: fix_string | string | integer.

πŸ’œ FUNCTIONS πŸ’œ

delete/1

delete(Index) -> true when Index :: index().

deletes a complete index structure (i.e. the ets table holding the index). the index can no longer be referenced after this call. see the warning note above, bestie, it's up there for a reason. 🚨

delete/2

delete(Index, Key) -> NewIndex
    when Index :: index(), Key :: key(), NewIndex :: index().

deletes a key and its value from the index structure. returns a new structure.

get/2

get(Index, KeyOid) -> {ok, {KeyOid, Value}} | undefined
    when Index :: index(), KeyOid :: snmp:oid(), Value :: term().

gets the item with key KeyOid. could be used from within an SNMP instrumentation function. πŸŽ€

get_last/1

get_last(Index) -> {ok, {KeyOid, Value}} | undefined
    when
        Index :: index(),
        KeyOid :: snmp:oid(),
        Value :: term().

gets the last item in the index structure. the finale. the last one. ⭐

get_next/2

get_next(Index, KeyOid) -> {ok, {NextKeyOid, Value}} | undefined
    when
        Index :: index(),
        KeyOid :: snmp:oid(),
        NextKeyOid :: snmp:oid(),
        Value :: term().

gets the next item in the SNMP lexicographic ordering, after KeyOid in the index structure. and lowkey the best part: KeyOid does not have to refer to an existing item in the index. it's giving flexible. πŸ”₯

insert/3

insert(Index, Key, Value) -> NewIndex
    when
        Index :: index(),
        Key :: key(),
        Value :: term(),
        NewIndex :: index().

inserts a new key value tuple into the index structure. if an item with the same key already exists, the new Value overwrites the old value. no hesitation, no mercy. πŸ’…

key_to_oid/2

key_to_oid(Index, Key) -> KeyOid
    when
        Index :: index(),
        Key :: key(),
        KeyOid :: snmp:oid().

converts Key to an OBJECT IDENTIFIER.

new/1

new(KeyTypes) -> Index
    when KeyTypes :: key_types(), Index :: index().

create a new anonymous snmp_index structure. mysterious. no name. very cunty of it honestly. 🧚

new/2

new(KeyTypes, Name) -> Index
    when
        KeyTypes :: key_types(),
        Name :: atom(),
        Index :: index().

creates a new named snmp_index structure. it has a name now, so it's official. πŸ‘‘


πŸ’– SEE ALSO πŸ’–

there's no SEE ALSO section in this one bestie, we're living self-sufficiently. periodt. 🌸


and that's the whole page, no cap. this one came from Ericsson AB, snmp version 5.20.5, and it's the snmp_index(3) manual page β€” go forth and index your tables, you absolute legend. πŸ’…βœ¨πŸ¦‹πŸ‘‘πŸ”₯

πŸ“¦ where this page comes from