0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: Documentation improvements

This commit is contained in:
Vojtech Vilimek 2023-11-16 07:11:14 +01:00
parent c18e6dd58d
commit a6a07ffb19
2 changed files with 70 additions and 16 deletions

View File

@ -8,7 +8,39 @@
*/
/**
* Simple Network Management Protocol State Machine
* DOC: Simple Network Management Protocol
*
* The SNMP protocol is divided into several parts: |snmp.c| which implements
* the BIRD intergration, |subagent.c| contains functions for creating and
* parsing packets, |bgp_mib.c| takes care of the bgp MIB subtree of standard
* BGP4-MIB and |snmp_utils.c| which is collections of helper functions for
* working with OIDs, VarBinds.
*
* Althrough called SNMP the BIRD does not implement SNMP directly but acts as
* an AgentX subagent. AgentX subagent connects to AgentX master agent that
* processes incomming SNMP requests and passes them down to the correct
* subagent. Therefore you need also a running master agent somewhere.
* Advantages of this design are that you are capable of doing aggregation of
* statuses of multiple BIRDs at the master agent level and much simpler
* implementation.
*
* Before any of the SNMP request could be processed, the SNMP need to
* established AgentX session with the master agent and need to register all
* subtrees to make them accessible from the master agent. The establishement of
* the of session is handled by snmp_start(), snmp_start_locked() and
* snmp_start_subagent(). Then we register all MIBs from configuration in
* snmp_register_mibs().
*
* The AgentX request are handled only during MIB subtree registrations and
* after then on established session (in states SNMP_REGISTER and SNMP_CONN, see
* below). It is also guaranteed that no request is received before MIB subtree
* registration because the specific subagent is not authoratitave and also the
* master agent has no info about MIB subtree supported by subagent. The AgentX
* requests are handled by function snmp_rx() in |subagent.c|.
*
*
*
* SNMP State Machine
*
* States with main transitions
*

View File

@ -28,23 +28,34 @@
*/
/**
*
*
*
*
* Handling of malformed packet:
* When we find an error in PDU data, we create and send a response with error
* defined by the RFC. We await until the packet is send and then we close the
* communication socket. This also closes the established session. We chose
* this approach because we cannot easily mark the boundary between packets.
* When we are reseting the connection, we change the snmp_state to SNMP_RESET.
* In SNMP_RESET state we skip all received bytes and wait for snmp_tx()
* to be called. The socket's tx_hook is called when the TX-buffer is empty,
* meaning our response (agentx-Response-PDU) was send.
*
* When we find an error in PDU data, we create and send a response with error
* defined by the RFC. We await until the packet is send and then we close the
* communication socket. This implicitly closes the established session. We
* chose this approach because we cannot easily mark the boundary between packets.
* When we are reseting the connection, we change the snmp_state to SNMP_RESET.
* In SNMP_RESET state we skip all received bytes and wait for snmp_tx()
* to be called. The socket's tx_hook is called when the TX-buffer is empty,
* meaning our response (agentx-Response-PDU) was send.
*
*
* Partial parsing
* It may happen that we received only staring part of some PDU from the
* communication socket. In most cases if we recognize this situation we
* immediately return, waiting for rest of the PDU to arrive. But for packets
* like agentx-Get-PDU, agentx-GetNext-PDU and agentx-GetBulk-PDU it could be
* costly as they could hold many VarBinds. In these cases we process.
* Partial parsing:
*
* It may happen that we received only staring part of some PDU from the
* communication socket. In most cases, if we recognize this situation we
* immediately return, waiting for rest of the PDU to arrive. But for packets
* like agentx-Get-PDU, agentx-GetNext-PDU and agentx-GetBulk-PDU it could be
* costly as they could hold many VarBinds. We don't want to process these
* packet twice because it is a lot work. We parse all VarBinds until we hit the
* first incomplete one. The logic behind this is to release as much as
* possible space from receive buffer. When we hit the first incomplete VarBind,
* we store information about the parsing state and move the header inside the
* receive buffer.
*
* Transmit packet context
*
@ -1498,6 +1509,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
{
res = p->last_header;
p->last_header = NULL;
p->last_size = 0;
}
else
res = response_header;
@ -1520,6 +1532,7 @@ partial:
STORE_U32(h->payload, pkt_size);
*skip = AGENTX_HEADER_SIZE;
p->last_header = h;
p->last_size = c.buffer - sk->tpos;
/* number of bytes parsed from RX-buffer */
ret = pkt - pkt_start;
@ -1632,7 +1645,16 @@ snmp_ping(struct snmp_proto *p)
snmp_pdu_context(&c, sk);
if (c.size < AGENTX_HEADER_SIZE)
snmp_manage_tbuf(p, &c);
return;
int unused = (sk->tbsize - (sk->tpos - sk->tbuf)) - (p->last_size + AGENTX_HEADER_SIZE);
if (p->last_header && unused >= 0)
{
}
else if (p->last_header)
{
}
struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);