Skip to content

Commit

Permalink
Merge pull request FRRouting#7945 from volta-networks/feat_isis_snmp
Browse files Browse the repository at this point in the history
isisd: add support for read-only snmp mibs objects
  • Loading branch information
rwestphal authored Mar 15, 2021
2 parents 70d453d + 0a43404 commit e1908ce
Show file tree
Hide file tree
Showing 53 changed files with 5,876 additions and 105 deletions.
17 changes: 14 additions & 3 deletions isisd/isis_adjacency.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,21 @@
#include "isisd/fabricd.h"
#include "isisd/isis_nb.h"

static struct isis_adjacency *adj_alloc(const uint8_t *id)
static struct isis_adjacency *adj_alloc(struct isis_circuit *circuit,
const uint8_t *id)
{
struct isis_adjacency *adj;

adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency));
memcpy(adj->sysid, id, ISIS_SYS_ID_LEN);

adj->snmp_idx = ++circuit->snmp_adj_idx_gen;

if (circuit->snmp_adj_list == NULL)
circuit->snmp_adj_list = list_new();

adj->snmp_list_node = listnode_add(circuit->snmp_adj_list, adj);

return adj;
}

Expand All @@ -65,7 +73,7 @@ struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
struct isis_adjacency *adj;
int i;

adj = adj_alloc(id); /* P2P kludge */
adj = adj_alloc(circuit, id); /* P2P kludge */

if (snpa) {
memcpy(adj->snpa, snpa, ETH_ALEN);
Expand Down Expand Up @@ -146,6 +154,8 @@ void isis_delete_adj(void *arg)

if (!adj)
return;
/* Remove self from snmp list without walking the list*/
list_delete_node(adj->circuit->snmp_adj_list, adj->snmp_list_node);

thread_cancel(&adj->t_expire);
if (adj->adj_state != ISIS_ADJ_DOWN)
Expand Down Expand Up @@ -292,7 +302,6 @@ void isis_adj_state_change(struct isis_adjacency **padj,
if (circuit->area->log_adj_changes)
isis_log_adj_change(adj, old_state, new_state, reason);

circuit->adj_state_changes++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_adj_state_change(adj, new_state, reason);
Expand All @@ -303,12 +312,14 @@ void isis_adj_state_change(struct isis_adjacency **padj,
if ((adj->level & level) == 0)
continue;
if (new_state == ISIS_ADJ_UP) {
circuit->adj_state_changes++;
circuit->upadjcount[level - 1]++;
/* update counter & timers for debugging
* purposes */
adj->last_flap = time(NULL);
adj->flaps++;
} else if (old_state == ISIS_ADJ_UP) {
circuit->adj_state_changes++;
listnode_delete(circuit->u.bc.adjdb[level - 1],
adj);

Expand Down
2 changes: 2 additions & 0 deletions isisd/isis_adjacency.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ struct isis_adjacency {
unsigned int mt_count; /* Number of entries in mt_set */
struct bfd_session *bfd_session;
struct list *adj_sids; /* Segment Routing Adj-SIDs. */
uint32_t snmp_idx;
struct listnode *snmp_list_node;
};

struct isis_threeway_adj;
Expand Down
74 changes: 74 additions & 0 deletions isisd/isis_circuit.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,48 @@ DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp))
int isis_if_new_hook(struct interface *);
int isis_if_delete_hook(struct interface *);

static int isis_circuit_smmp_id_gen(struct isis_circuit *circuit)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct isis *isis = NULL;
uint32_t id;
uint32_t i;

isis = isis_lookup_by_vrfid(vrf->vrf_id);
if (isis == NULL)
return 0;

id = isis->snmp_circuit_id_last;
id++;

/* find next unused entry */
for (i = 0; i < SNMP_CIRCUITS_MAX; i++) {
if (id >= SNMP_CIRCUITS_MAX) {
id = 0;
continue;
}

if (id == 0)
continue;

if (isis->snmp_circuits[id] == NULL)
break;

id++;
}

if (i == SNMP_CIRCUITS_MAX) {
zlog_warn("Could not allocate a smmp-circuit-id");
return 0;
}

isis->snmp_circuits[id] = circuit;
isis->snmp_circuit_id_last = id;
circuit->snmp_id = id;

return 1;
}

struct isis_circuit *isis_circuit_new(struct isis *isis)
{
struct isis_circuit *circuit;
Expand All @@ -79,6 +121,12 @@ struct isis_circuit *isis_circuit_new(struct isis *isis)
circuit = XCALLOC(MTYPE_ISIS_CIRCUIT, sizeof(struct isis_circuit));

circuit->isis = isis;
/*
* Note: if snmp-id generation failed circuit will fail
* up operation
*/
isis_circuit_smmp_id_gen(circuit);

/*
* Default values
*/
Expand Down Expand Up @@ -150,11 +198,18 @@ struct isis_circuit *isis_circuit_new(struct isis *isis)

void isis_circuit_del(struct isis_circuit *circuit)
{
struct isis *isis = NULL;

if (!circuit)
return;

QOBJ_UNREG(circuit);

if (circuit->interface) {
isis = isis_lookup_by_vrfid(circuit->interface->vrf_id);
isis->snmp_circuits[circuit->snmp_id] = NULL;
}

isis_circuit_if_unbind(circuit, circuit->interface);

circuit_mt_finish(circuit);
Expand Down Expand Up @@ -609,6 +664,7 @@ int isis_circuit_up(struct isis_circuit *circuit)
return ISIS_OK;

if (circuit->is_passive) {
circuit->last_uptime = time(NULL);
/* make sure the union fields are initialized, else we
* could end with garbage values from a previous circuit
* type, which would then cause a segfault when building
Expand All @@ -623,6 +679,13 @@ int isis_circuit_up(struct isis_circuit *circuit)
return ISIS_OK;
}

if (circuit->snmp_id == 0) {
/* We cannot bring circuit up if does not have snmp-id */
flog_err(EC_ISIS_CONFIG,
"No snnmp-id: there are too many circuits:");
return ISIS_ERROR;
}

if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) {
flog_err(
EC_ISIS_CONFIG,
Expand Down Expand Up @@ -722,6 +785,8 @@ int isis_circuit_up(struct isis_circuit *circuit)

circuit->tx_queue = isis_tx_queue_new(circuit, send_lsp);

circuit->last_uptime = time(NULL);

#ifndef FABRICD
/* send northbound notification */
isis_notif_if_state_change(circuit, false);
Expand Down Expand Up @@ -828,6 +893,15 @@ void isis_circuit_down(struct isis_circuit *circuit)
thread_cancel(&circuit->u.p2p.t_send_p2p_hello);
}

/*
* All adjacencies have to be gone, delete snmp list
* and reset snmpd idx generator
*/
if (circuit->snmp_adj_list != NULL)
list_delete(&circuit->snmp_adj_list);

circuit->snmp_adj_idx_gen = 0;

/* Cancel all active threads */
thread_cancel(&circuit->t_send_csnp[0]);
thread_cancel(&circuit->t_send_csnp[1]);
Expand Down
9 changes: 9 additions & 0 deletions isisd/isis_circuit.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct isis_circuit_arg {
struct isis_circuit {
int state;
uint8_t circuit_id; /* l1/l2 bcast CircuitID */
time_t last_uptime;
struct isis *isis;
struct isis_area *area; /* back pointer to the area */
struct interface *interface; /* interface info from z */
Expand Down Expand Up @@ -115,6 +116,8 @@ struct isis_circuit {
int pad_hellos; /* add padding to Hello PDUs ? */
char ext_domain; /* externalDomain (boolean) */
int lsp_regenerate_pending[ISIS_LEVELS];
uint64_t lsp_error_counter;

/*
* Configurables
*/
Expand Down Expand Up @@ -165,6 +168,12 @@ struct isis_circuit {
uint32_t auth_type_failures; /*authentication-type-fails */
uint32_t auth_failures; /* authentication-fails */

uint32_t snmp_id; /* Circuit id in snmp */

uint32_t snmp_adj_idx_gen; /* Create unique id for adjacency on creation
*/
struct list *snmp_adj_list; /* List in id order */

QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(isis_circuit)
Expand Down
1 change: 1 addition & 0 deletions isisd/isis_dr.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static int isis_check_dr_change(struct isis_adjacency *adj, int level)
/* was there a DIS state transition ? */
{
adj->dischanges[level - 1]++;
adj->circuit->desig_changes[level - 1]++;
/* ok rotate the history list through */
for (i = DIS_RECORDS - 1; i > 0; i--) {
adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis =
Expand Down
35 changes: 35 additions & 0 deletions isisd/isis_dynhn.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,38 @@ void dynhn_print_all(struct vty *vty, struct isis *isis)
cmd_hostname_get());
return;
}

struct isis_dynhn *dynhn_snmp_next(const uint8_t *id, int level)
{
struct listnode *node = NULL;
struct isis_dynhn *dyn = NULL;
struct isis_dynhn *found_dyn = NULL;
int res;

for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) {
res = memcmp(dyn->id, id, ISIS_SYS_ID_LEN);

if (res < 0)
continue;

if (res == 0 && dyn->level <= level)
continue;

if (res == 0) {
/*
* This is the best match, we can stop
* searching
*/

found_dyn = dyn;
break;
}

if (found_dyn == NULL
|| memcmp(dyn->id, found_dyn->id, ISIS_SYS_ID_LEN) < 0) {
found_dyn = dyn;
}
}

return found_dyn;
}
3 changes: 3 additions & 0 deletions isisd/isis_dynhn.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ struct isis_dynhn *dynhn_find_by_id(const uint8_t *id);
struct isis_dynhn *dynhn_find_by_name(const char *hostname);
void dynhn_print_all(struct vty *vty, struct isis *isis);

/* Snmp support */
struct isis_dynhn *dynhn_snmp_next(const uint8_t *id, int level);

#endif /* _ZEBRA_ISIS_DYNHN_H */
8 changes: 4 additions & 4 deletions isisd/isis_lsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,8 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
/* check for overflow */
if (newseq < lsp->hdr.seqno) {
/* send northbound notification */
isis_notif_lsp_exceed_max(lsp->area,
rawlspid_print(lsp->hdr.lsp_id));
lsp->area->lsp_exceeded_max_counter++;
isis_notif_lsp_exceed_max(lsp->area, lsp->hdr.lsp_id);
}
#endif /* ifndef FABRICD */

Expand Down Expand Up @@ -1357,8 +1357,8 @@ int lsp_generate(struct isis_area *area, int level)

#ifndef FABRICD
/* send northbound notification */
isis_notif_lsp_gen(area, rawlspid_print(newlsp->hdr.lsp_id),
newlsp->hdr.seqno, newlsp->last_generated);
isis_notif_lsp_gen(area, newlsp->hdr.lsp_id, newlsp->hdr.seqno,
newlsp->last_generated);
#endif /* ifndef FABRICD */

return ISIS_OK;
Expand Down
Loading

0 comments on commit e1908ce

Please sign in to comment.