0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-21 22:07:03 +00:00

Testing Notify-PDU

This commit is contained in:
Vojtech Vilimek 2023-09-04 09:25:51 +02:00
parent 3c718d162c
commit df28d1cbe8
4 changed files with 589 additions and 211 deletions

View File

@ -70,9 +70,7 @@ snmp_bgp_register(struct snmp_proto *p)
add_tail(&p->register_queue, &registering->n); add_tail(&p->register_queue, &registering->n);
p->register_to_ack++; p->register_to_ack++;
/* Function declartion: /* snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance) */
* snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance);
*/
snmp_register(p, oid, 0, 1, 0); snmp_register(p, oid, 0, 1, 0);
} }
} }
@ -114,11 +112,10 @@ bgp_get_candidate(u32 field)
}; };
/* /*
* First value is in secord cell of array translation_table (as the * First value is in secord cell of array translation_table, as the
* SNMP_BPG_IDENTIFIER == 1 * SNMP_BPG_IDENTIFIER == 1
*/ */
if (field > 0 && if (field > 0 && field <= sizeof(translation_table) / sizeof(translation_table[0]) - 1)
field <= sizeof(translation_table)/sizeof(translation_table[0]) - 1)
return translation_table[field]; return translation_table[field];
if (field == 0) if (field == 0)
return BGP_INTERNAL_INVALID; return BGP_INTERNAL_INVALID;
@ -193,6 +190,7 @@ print_bgp_record_all(struct snmp_proto *p)
snmp_log("dumping watched end"); snmp_log("dumping watched end");
} }
/** /**
* snmp_bgp_state - linearize oid from BGP4-MIB * snmp_bgp_state - linearize oid from BGP4-MIB
* @oid: prefixed object identifier from BGP4-MIB::bgp subtree * @oid: prefixed object identifier from BGP4-MIB::bgp subtree
@ -402,7 +400,7 @@ update_bgp_oid(struct oid *oid, u8 state)
state == BGP_INTERNAL_NO_VALUE) state == BGP_INTERNAL_NO_VALUE)
return oid; return oid;
/* No need to reallocate anything if the OID is has same lin. state */ /* No need to reallocate anything if the OID has same lin. state */
if (snmp_bgp_state(oid) == state) if (snmp_bgp_state(oid) == state)
{ {
if (state >= BGP_INTERNAL_IDENTIFIER && if (state >= BGP_INTERNAL_IDENTIFIER &&
@ -537,6 +535,7 @@ update_bgp_oid(struct oid *oid, u8 state)
default: default:
/* intentionally left blank */ /* intentionally left blank */
break; break;
//die("update unavailable");
} }
return oid; return oid;
@ -590,10 +589,7 @@ bgp_find_dynamic_oid(struct snmp_proto *p, struct oid *o_start, const struct oid
if (cmp < 0 || (cmp == 0 && snmp_is_oid_empty(o_end))) if (cmp < 0 || (cmp == 0 && snmp_is_oid_empty(o_end)))
{ {
snmp_log("ip4_less() returned true"); snmp_log("ip4_less() returned true");
struct oid *o = mb_allocz(p->p.pool, snmp_oid_sizeof(9)); struct oid *o = snmp_oid_duplicate(p->p.pool, o_start);
o->n_subid = 9;
memcpy(o, o_start, snmp_oid_size(o_start));
snmp_oid_ip4_index(o, 5, net4_prefix(&net)); snmp_oid_ip4_index(o, 5, net4_prefix(&net));
return o; return o;
@ -627,7 +623,7 @@ UNUSED, u8 current_state)
snmp_oid_dump(o_start); snmp_oid_dump(o_start);
next_state = snmp_bgp_next_state(next_state); next_state = snmp_bgp_next_state(next_state);
/* We search in next state is done from beginning. */ /* The search in next state is done from beginning. */
o_start->ids[5] = o_start->ids[6] = o_start->ids[7] = o_start->ids[8] = 0; o_start->ids[5] = o_start->ids[6] = o_start->ids[7] = o_start->ids[8] = 0;
o_start->include = 1; o_start->include = 1;
@ -647,7 +643,6 @@ UNUSED, u8 current_state)
static int static int
snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid) snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid)
{ {
// TODO add o_end paramenter for faster searches
ip4_addr ip4 = ip4_from_oid(oid); ip4_addr ip4 = ip4_from_oid(oid);
//ip_add4 dest = ip4_from_u32(0xFFFFFFFF); //ip_add4 dest = ip4_from_u32(0xFFFFFFFF);
@ -722,7 +717,7 @@ snmp_bgp_search_dynamic(struct snmp_proto *p, struct oid **searched, const struc
oid->ids[5] = oid->ids[6] = oid->ids[7] = oid->ids[8] = 0; oid->ids[5] = oid->ids[6] = oid->ids[7] = oid->ids[8] = 0;
} }
if (next_state <= end_state) if (next_state < BGP_INTERNAL_END && next_state <= end_state)
{ {
*searched = oid; *searched = oid;
return SNMP_SEARCH_OK; return SNMP_SEARCH_OK;
@ -740,6 +735,11 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *
struct oid *oid = *searched; struct oid *oid = *searched;
snmp_log("snmp_bgp_search2() with state %s [%d]", debug_bgp_states[bgp_state], bgp_state); snmp_log("snmp_bgp_search2() with state %s [%d]", debug_bgp_states[bgp_state], bgp_state);
if (bgp_state == BGP_INTERNAL_END)
{
return SNMP_SEARCH_NO_OBJECT;
}
/* TODO remove todo below, then remove this code */ /* TODO remove todo below, then remove this code */
if (is_dynamic(bgp_state)) if (is_dynamic(bgp_state))
{ {
@ -773,7 +773,8 @@ snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *
oid = *searched = update_bgp_oid(*searched, bgp_state); oid = *searched = update_bgp_oid(*searched, bgp_state);
if (oid->n_subid == 3 && oid->ids[2] >= SNMP_BGP_VERSION && if (oid->n_subid == 3 && oid->ids[2] >= SNMP_BGP_VERSION &&
oid->ids[2] <= SNMP_BGP_LOCAL_AS) oid->ids[2] <= SNMP_BGP_LOCAL_AS && bgp_state != BGP_INTERNAL_END)
//oid->ids[2] <= SNMP_BGP_LOCAL_AS && bgp_state != BGP_INTERNAL_END)
{ {
snmp_log("oid matches static state"); snmp_log("oid matches static state");
oid->include = 0; oid->include = 0;
@ -789,8 +790,8 @@ struct oid *
snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid UNUSED) snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, uint contid UNUSED)
{ {
u8 start_state = snmp_bgp_state(o_start); u8 start_state = snmp_bgp_state(o_start);
//u8 state_curr = snmp_bgp_state(o_start);
//u8 state_end = (o_end) ? snmp_bgp_state(o_end) : 0; // print debugging information
print_bgp_record_all(p); print_bgp_record_all(p);
if (o_start->include && snmp_bgp_has_value(start_state) && if (o_start->include && snmp_bgp_has_value(start_state) &&
@ -808,7 +809,7 @@ snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, ui
return search_bgp_dynamic(p, o_start, o_end, contid, start_state); return search_bgp_dynamic(p, o_start, o_end, contid, start_state);
} }
/* o_start->include == 0 */ /* o_start is not inclusive */
u8 next_state = snmp_bgp_next_state(start_state); u8 next_state = snmp_bgp_next_state(start_state);
// TODO more checks ?!? // TODO more checks ?!?
@ -844,6 +845,8 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb,
} }
snmp_log(" -> ip addr %I", addr); snmp_log(" -> ip addr %I", addr);
// TODO XXX deal with possible change of (remote) ip; BGP should restart and
// disappear
struct snmp_bgp_peer *pe = HASH_FIND(p->bgp_hash, SNMP_HASH, addr); struct snmp_bgp_peer *pe = HASH_FIND(p->bgp_hash, SNMP_HASH, addr);
struct bgp_proto *bgp_proto = NULL; struct bgp_proto *bgp_proto = NULL;

View File

@ -7,6 +7,68 @@
* Can be freely distributed and used under the terms of the GNU GPL. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
/**
* Simple Network Management Protocol State Machine
*
* States with main transitions
*
*
* +-----------------+
* | SNMP_INIT | entry state after call snmp_start()
* +-----------------+
* |
* | acquiring object lock for communication socket
* V
* +-----------------+
* | SNMP_LOCKED | object lock aquired
* +-----------------+
* |
* | opening communaiton socket
* V
* +-----------------+
* | SNMP_OPEN | socket created, starting subagent
* +-----------------+
* |
* | BIRD recieve response for Open-PDU
* V
* +-----------------+
* | SNMP_REGISTER | session was established, subagent registers MIBs
* +-----------------+
* |
* | subagent recieved responses for all registration requests
* V
* +-----------------+
* | SNMP_CONN | everything is set
* +-----------------+
* |
* | function snmp_shutdown() is called, BIRD sends Close-PDU
* V
* +-----------------+
* | SNMP_STOP | waiting for response
* +-----------------+
* |
* | cleaning old state information
* V
* +-----------------+
* | SNMP_DOWN | session is closed
* +-----------------+
*
*
* Erroneous transitions:
* SNMP is UP in states SNMP_CONN and also in SNMP_REGISTER because the
* session is establised and the GetNext request should be responsed
* without regard to MIB registration.
*
* When the session has been closed for some reason (socket error, reciept of
* Close-PDU) SNMP cleans the session information and message queue and goes
* back to the SNMP_LOCKED state.
*
* Reconfiguration is done in similar fashion to BGP, the reconfiguration
* request is declined, the protocols is stoped and started with new
* configuration.
*
*/
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/cli.h" #include "nest/cli.h"
#include "nest/locks.h" #include "nest/locks.h"
@ -26,6 +88,15 @@ static void snmp_start_locked(struct object_lock *lock);
static int snmp_shutdown(struct proto *P); static int snmp_shutdown(struct proto *P);
static const char * const snmp_state[] = { static const char * const snmp_state[] = {
[SNMP_ERR] = "SNMP ERROR",
[SNMP_INIT] = "SNMP INIT",
[SNMP_LOCKED] = "SNMP LOCKED",
[SNMP_OPEN] = "SNMP CONNECTION OPENED",
[SNMP_REGISTER] = "SNMP REGISTERING MIBS",
[SNMP_CONN] = "SNMP CONNECTED",
[SNMP_STOP] = "SNMP STOPING",
[SNMP_DOWN] = "SNMP DOWN",
/*
[SNMP_ERR] = "SNMP ERROR", [SNMP_ERR] = "SNMP ERROR",
[SNMP_DELAY] = "SNMP DELAY", [SNMP_DELAY] = "SNMP DELAY",
[SNMP_INIT] = "SNMP INIT", [SNMP_INIT] = "SNMP INIT",
@ -34,6 +105,7 @@ static const char * const snmp_state[] = {
[SNMP_STOP] = "SNMP STOP", [SNMP_STOP] = "SNMP STOP",
[SNMP_DOWN] = "SNMP DOWN", [SNMP_DOWN] = "SNMP DOWN",
[SNMP_LISTEN] = "SNMP LISTEN", [SNMP_LISTEN] = "SNMP LISTEN",
*/
}; };
static struct proto * static struct proto *
@ -110,10 +182,12 @@ snmp_startup(struct snmp_proto *p)
{ {
//snmp_log("changing proto_snmp state to INIT"); //snmp_log("changing proto_snmp state to INIT");
if (p->state == SNMP_CONN || if (p->state == SNMP_LOCKED ||
p->state == SNMP_REGISTER) p->state == SNMP_OPEN ||
p->state == SNMP_REGISTER ||
p->state == SNMP_CONN)
{ {
snmp_log("startup() with invalid state %u", p->state); snmp_log("startup() already in connected state %u", p->state);
return; return;
} }
@ -151,6 +225,8 @@ snmp_start_locked(struct object_lock *lock)
snmp_log("snmp_start_locked() - lock acquired; preparing socket"); snmp_log("snmp_start_locked() - lock acquired; preparing socket");
struct snmp_proto *p = lock->data; struct snmp_proto *p = lock->data;
p->state = SNMP_LOCKED;
sock *s = sk_new(p->p.pool); sock *s = sk_new(p->p.pool);
s->type = SK_TCP_ACTIVE; s->type = SK_TCP_ACTIVE;
s->saddr = p->local_ip; s->saddr = p->local_ip;
@ -185,6 +261,9 @@ snmp_connected(sock *sk)
{ {
struct snmp_proto *p = sk->data; struct snmp_proto *p = sk->data;
snmp_log("snmp_connected() connection created"); snmp_log("snmp_connected() connection created");
p->state = SNMP_OPEN;
byte *buf UNUSED = sk->rpos; byte *buf UNUSED = sk->rpos;
sk->rx_hook = snmp_rx; sk->rx_hook = snmp_rx;
@ -392,8 +471,8 @@ snmp_shutdown(struct proto *P)
tm_stop(p->ping_timer); tm_stop(p->ping_timer);
/* connection established -> close the connection */ /* connection established -> close the connection */
if (p->state == SNMP_CONN || if (p->state == SNMP_REGISTER ||
p->state == SNMP_REGISTER) p->state == SNMP_CONN)
{ {
p->state = SNMP_STOP; p->state = SNMP_STOP;
@ -407,7 +486,6 @@ snmp_shutdown(struct proto *P)
return PS_STOP; return PS_STOP;
} }
/* no connection to close */ /* no connection to close */
else else
{ {
@ -435,3 +513,4 @@ snmp_build(void)
{ {
proto_build(&proto_snmp); proto_build(&proto_snmp);
} }

View File

@ -31,6 +31,17 @@
enum snmp_proto_state { enum snmp_proto_state {
SNMP_ERR = 0, SNMP_ERR = 0,
SNMP_INIT = 1,
SNMP_LOCKED,
SNMP_OPEN,
SNMP_REGISTER,
SNMP_CONN,
SNMP_STOP,
SNMP_DOWN,
/*
SNMP_ERR = 0,
SNMP_DELAY, SNMP_DELAY,
SNMP_INIT, SNMP_INIT,
SNMP_REGISTER, SNMP_REGISTER,
@ -38,6 +49,8 @@ enum snmp_proto_state {
SNMP_STOP, SNMP_STOP,
SNMP_DOWN, SNMP_DOWN,
SNMP_LISTEN, SNMP_LISTEN,
SNMP_RESET,
*/
}; };
/* hash table macros */ /* hash table macros */

File diff suppressed because it is too large Load Diff