summaryrefslogtreecommitdiffstats
path: root/isisd/isis_nb_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_nb_state.c')
-rw-r--r--isisd/isis_nb_state.c630
1 files changed, 630 insertions, 0 deletions
diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c
new file mode 100644
index 0000000..b7c33ed
--- /dev/null
+++ b/isisd/isis_nb_state.c
@@ -0,0 +1,630 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Volta Networks
+ * Emanuele Di Pascale
+ */
+
+#include <zebra.h>
+
+#include "northbound.h"
+#include "linklist.h"
+
+#include "isisd/isisd.h"
+#include "isisd/isis_nb.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_misc.h"
+
+/*
+ * XPath: /frr-interface:lib/interface/state/frr-isisd:isis
+ */
+struct yang_data *
+lib_interface_state_isis_get_elem(struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit || !circuit->area)
+ return NULL;
+
+ return yang_data_new(args->xpath, NULL);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency
+ */
+const void *lib_interface_state_isis_adjacencies_adjacency_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj = NULL, *adj_next = NULL;
+ struct list *list;
+ struct listnode *node, *node_next;
+
+ /* Get first adjacency. */
+ if (args->list_entry == NULL) {
+ ifp = (struct interface *)args->parent_list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS;
+ level++) {
+ struct list *adjdb;
+
+ adjdb = circuit->u.bc.adjdb[level - 1];
+ if (adjdb) {
+ adj = listnode_head(adjdb);
+ if (adj)
+ break;
+ }
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ break;
+ default:
+ break;
+ }
+
+ return adj;
+ }
+
+ /* Get next adjacency. */
+ adj = (struct isis_adjacency *)args->list_entry;
+ circuit = adj->circuit;
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ list = circuit->u.bc.adjdb[adj->level - 1];
+ node = listnode_lookup(list, adj);
+ node_next = listnextnode(node);
+ if (node_next)
+ adj_next = listgetdata(node_next);
+ else if (adj->level == ISIS_LEVEL1) {
+ /*
+ * Once we finish the L1 adjacencies, move to the L2
+ * adjacencies list.
+ */
+ list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1];
+ adj_next = listnode_head(list);
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ /* P2P circuits have at most one adjacency. */
+ default:
+ break;
+ }
+
+ return adj_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_neighbor_sys_type_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+
+ return yang_data_new_enum(args->xpath, adj->level);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_neighbor_sysid_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+ char xpath_value[ISO_SYSID_STRLEN];
+
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid);
+
+ return yang_data_new_string(args->xpath, xpath_value);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+
+ return yang_data_new_uint32(args->xpath, adj->circuit->circuit_id);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+ char xpath_value[ISO_SYSID_STRLEN];
+
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->snpa);
+
+ return yang_data_new_string(args->xpath, xpath_value);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/hold-timer
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_hold_timer_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+
+ return yang_data_new_uint16(args->xpath, adj->hold_time);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/neighbor-priority
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+
+ return yang_data_new_uint8(args->xpath, adj->prio[adj->level - 1]);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/state
+ */
+struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct isis_adjacency *adj = args->list_entry;
+
+ return yang_data_new_string(args->xpath,
+ isis_adj_yang_state(adj->adj_state));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_bool(args->xpath,
+ sra->u.adj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->family);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->weight);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_bool(args->xpath,
+ sra->u.ladj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_adjacency_changes_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->adj_state_changes);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-number
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_adjacency_number_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj;
+ struct listnode *node;
+ uint32_t total = 0;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ /*
+ * TODO: keep track of the number of adjacencies instead of calculating
+ * it on demand.
+ */
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
+ for (ALL_LIST_ELEMENTS_RO(
+ circuit->u.bc.adjdb[level - 1], node, adj))
+ total++;
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ if (adj)
+ total = 1;
+ break;
+ default:
+ break;
+ }
+
+ return yang_data_new_uint32(args->xpath, total);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/init-fails
+ */
+struct yang_data *lib_interface_state_isis_event_counters_init_fails_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->init_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-rejects
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_adjacency_rejects_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->rej_adjacencies);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/id-len-mismatch
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_id_len_mismatch_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->id_len_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/max-area-addresses-mismatch
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_max_area_addresses_mismatch_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath,
+ circuit->max_area_addr_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-type-fails
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_authentication_type_fails_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->auth_type_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/authentication-fails
+ */
+struct yang_data *
+lib_interface_state_isis_event_counters_authentication_fails_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)args->list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath, circuit->auth_failures);
+}