From e206450bd9a74ae782bc020b6d5bbba722ae0c09 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 23 Sep 2019 09:37:57 -0300 Subject: [PATCH 1/3] yang: create new interface-config grouping in the frr-isisd module Do this to better separate config data from state data (coming in the next commits) like done in the IETF IS-IS module. Signed-off-by: Renato Westphal --- yang/frr-isisd.yang | 534 ++++++++++++++++++++++---------------------- 1 file changed, 270 insertions(+), 264 deletions(-) diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 3313dc2f20..b0f395fea8 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -275,6 +275,275 @@ module frr-isisd { } } + grouping interface-config { + description "Interface configuration grouping"; + + leaf area-tag { + type string; + mandatory true; + description + "Area-tag associated to this circuit."; + } + + leaf ipv4-routing { + type boolean; + default "false"; + description + "Routing IS-IS IPv4 traffic over this circuit."; + } + + leaf ipv6-routing { + type boolean; + default "false"; + description + "Routing IS-IS IPv6 traffic over this circuit."; + } + + leaf circuit-type { + type level; + default "level-1-2"; + description + "IS-type of this circuit."; + } + + leaf bfd-monitoring { + type boolean; + default false; + description "Monitor IS-IS peers on this circuit."; + } + + container csnp-interval { + description + "Complete Sequence Number PDU (CSNP) generation interval."; + leaf level-1 { + type uint16 { + range "1..600"; + } + units "seconds"; + default "10"; + description + "CNSP interval for level-1"; + } + + leaf level-2 { + type uint16 { + range "1..600"; + } + units "seconds"; + default "10"; + description + "CNSP interval for level-2"; + } + } + + container psnp-interval { + description + "Partial Sequence Number PDU (PSNP) generation interval."; + leaf level-1 { + type uint16 { + range "1..120"; + } + units "seconds"; + default "2"; + description + "PNSP interval for level-1"; + } + + leaf level-2 { + type uint16 { + range "1..120"; + } + units "seconds"; + default "2"; + description + "PCNSP interval for level-2"; + } + } + + container hello { + description + "Parameters related to IS-IS hello PDUs."; + leaf padding { + type boolean; + default "true"; + description + "Add padding to IS-IS hello PDUs."; + } + + container interval { + description + "Interval between consecutive hello messages."; + leaf level-1 { + type uint32 { + range "1..600"; + } + units "seconds"; + default "3"; + description + "Holding time for level-1; interval will depend on multiplier."; + } + + leaf level-2 { + type uint32 { + range "1..600"; + } + units "seconds"; + default "3"; + description + "Holding time for level-2; interval will depend on multiplier."; + } + } + + container multiplier { + description + "Multiplier for the hello messages holding time."; + leaf level-1 { + type uint16 { + range "2..100"; + } + default "10"; + description + "Multiplier for the hello holding time."; + } + + leaf level-2 { + type uint16 { + range "2..100"; + } + default "10"; + description + "Multiplier for the hello holding time."; + } + } + } + + container metric { + description + "Default metric for this IS-IS circuit."; + leaf level-1 { + type uint32 { + range "0..16777215"; + } + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + default "10"; + description + "Default level-1 metric for this IS-IS circuit."; + } + + leaf level-2 { + type uint32 { + range "0..16777215"; + } + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + default "10"; + description + "Default level-2 metric for this IS-IS circuit."; + } + } + + container priority { + description + "Priority for Designated Router election."; + leaf level-1 { + type uint8 { + range "0..127"; + } + default "64"; + description + "Level-1 priority for this IS-IS circuit."; + } + + leaf level-2 { + type uint8 { + range "0..127"; + } + default "64"; + description + "Level-2 priority for this IS-IS circuit."; + } + } + + leaf network-type { + type network-type; + default "broadcast"; + must "(. = \"point-to-point\") or (. = \"broadcast\")"; + description + "Explicitly configured type of IS-IS circuit (broadcast or point-to-point)."; + } + + leaf passive { + type boolean; + default "false"; + description + "Interface is in passive mode."; + } + + container password { + presence "Present if a password is set for this IS interface."; + uses isis-password; + } + + leaf disable-three-way-handshake { + type boolean; + default "false"; + description + "Disables three-way handshake when creating new adjacencies."; + } + + container multi-topology { + description + "IS-IS topologies configured on this circuit."; + leaf ipv4-unicast { + type boolean; + default "true"; + description + "IPv4 unicast topology."; + } + + leaf ipv4-multicast { + type boolean; + default "true"; + description + "IPv4 multicast topology."; + } + + leaf ipv4-management { + type boolean; + default "true"; + description + "IPv4 management topology."; + } + + leaf ipv6-unicast { + type boolean; + default "true"; + description + "IPv6 unicast topology."; + } + + leaf ipv6-multicast { + type boolean; + default "true"; + description + "IPv6 multicast topology."; + } + + leaf ipv6-management { + type boolean; + default "true"; + description + "IPv6 management topology."; + } + + leaf ipv6-dstsrc { + type boolean; + default "true"; + description + "IPv6 destination-source topology."; + } + } + } + grouping notification-instance-hdr { description "Instance specific IS-IS notification data grouping"; @@ -733,270 +1002,7 @@ module frr-isisd { presence "Present if an IS-IS circuit is defined for this interface."; description "IS-IS interface parameters."; - leaf area-tag { - type string; - mandatory true; - description - "Area-tag associated to this circuit."; - } - - leaf ipv4-routing { - type boolean; - default "false"; - description - "Routing IS-IS IPv4 traffic over this circuit."; - } - - leaf ipv6-routing { - type boolean; - default "false"; - description - "Routing IS-IS IPv6 traffic over this circuit."; - } - - leaf circuit-type { - type level; - default "level-1-2"; - description - "IS-type of this circuit."; - } - - leaf bfd-monitoring { - type boolean; - default false; - description "Monitor IS-IS peers on this circuit."; - } - - container csnp-interval { - description - "Complete Sequence Number PDU (CSNP) generation interval."; - leaf level-1 { - type uint16 { - range "1..600"; - } - units "seconds"; - default "10"; - description - "CNSP interval for level-1"; - } - - leaf level-2 { - type uint16 { - range "1..600"; - } - units "seconds"; - default "10"; - description - "CNSP interval for level-2"; - } - } - - container psnp-interval { - description - "Partial Sequence Number PDU (PSNP) generation interval."; - leaf level-1 { - type uint16 { - range "1..120"; - } - units "seconds"; - default "2"; - description - "PNSP interval for level-1"; - } - - leaf level-2 { - type uint16 { - range "1..120"; - } - units "seconds"; - default "2"; - description - "PCNSP interval for level-2"; - } - } - - container hello { - description - "Parameters related to IS-IS hello PDUs."; - leaf padding { - type boolean; - default "true"; - description - "Add padding to IS-IS hello PDUs."; - } - - container interval { - description - "Interval between consecutive hello messages."; - leaf level-1 { - type uint32 { - range "1..600"; - } - units "seconds"; - default "3"; - description - "Holding time for level-1; interval will depend on multiplier."; - } - - leaf level-2 { - type uint32 { - range "1..600"; - } - units "seconds"; - default "3"; - description - "Holding time for level-2; interval will depend on multiplier."; - } - } - - container multiplier { - description - "Multiplier for the hello messages holding time."; - leaf level-1 { - type uint16 { - range "2..100"; - } - default "10"; - description - "Multiplier for the hello holding time."; - } - - leaf level-2 { - type uint16 { - range "2..100"; - } - default "10"; - description - "Multiplier for the hello holding time."; - } - } - } - - container metric { - description - "Default metric for this IS-IS circuit."; - leaf level-1 { - type uint32 { - range "0..16777215"; - } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; - default "10"; - description - "Default level-1 metric for this IS-IS circuit."; - } - - leaf level-2 { - type uint32 { - range "0..16777215"; - } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; - default "10"; - description - "Default level-2 metric for this IS-IS circuit."; - } - } - - container priority { - description - "Priority for Designated Router election."; - leaf level-1 { - type uint8 { - range "0..127"; - } - default "64"; - description - "Level-1 priority for this IS-IS circuit."; - } - - leaf level-2 { - type uint8 { - range "0..127"; - } - default "64"; - description - "Level-2 priority for this IS-IS circuit."; - } - } - - leaf network-type { - type network-type; - default "broadcast"; - must "(. = \"point-to-point\") or (. = \"broadcast\")"; - description - "Explicitly configured type of IS-IS circuit (broadcast or point-to-point)."; - } - - leaf passive { - type boolean; - default "false"; - description - "Interface is in passive mode."; - } - - container password { - presence "Present if a password is set for this IS interface."; - uses isis-password; - } - - leaf disable-three-way-handshake { - type boolean; - default "false"; - description - "Disables three-way handshake when creating new adjacencies."; - } - - container multi-topology { - description - "IS-IS topologies configured on this circuit."; - leaf ipv4-unicast { - type boolean; - default "true"; - description - "IPv4 unicast topology."; - } - - leaf ipv4-multicast { - type boolean; - default "true"; - description - "IPv4 multicast topology."; - } - - leaf ipv4-management { - type boolean; - default "true"; - description - "IPv4 management topology."; - } - - leaf ipv6-unicast { - type boolean; - default "true"; - description - "IPv6 unicast topology."; - } - - leaf ipv6-multicast { - type boolean; - default "true"; - description - "IPv6 multicast topology."; - } - - leaf ipv6-management { - type boolean; - default "true"; - description - "IPv6 management topology."; - } - - leaf ipv6-dstsrc { - type boolean; - default "true"; - description - "IPv6 destination-source topology."; - } - } + uses interface-config; } } From aec5ef490cfa2495aa1ab22cedd46659fd2366b6 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 23 Sep 2019 09:38:01 -0300 Subject: [PATCH 2/3] isisd, yang: implement read-only list of adjacencies The new "adjacency-state" grouping is almost a 1:1 copy of the same grouping from the IETF IS-IS module, except for the "usage" and "lastuptime" leafs that were skipped (more work needs to be done to support those). Signed-off-by: Renato Westphal --- isisd/isis_northbound.c | 242 +++++++++++++++++++++++++++++++++++++--- yang/frr-isisd.yang | 88 ++++++++++++++- 2 files changed, 316 insertions(+), 14 deletions(-) diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index bd61918697..7eba4791af 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -48,6 +48,23 @@ #include "lib/lib_errors.h" #include "lib/vrf.h" +/* + * Helper functions. + */ +static const char *isis_yang_adj_state(enum isis_adj_state state) +{ + switch (state) { + case ISIS_ADJ_DOWN: + return "down"; + case ISIS_ADJ_UP: + return "up"; + case ISIS_ADJ_INITIALIZING: + return "init"; + default: + return "failed"; + } +} + /* * XPath: /frr-isisd:isis/instance */ @@ -2303,6 +2320,169 @@ static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( ISIS_MT_IPV6_DSTSRC); } +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency + */ +static const void * +lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj, *adj_next = NULL; + struct list *list; + struct listnode *node, *node_next; + + /* Get first adjacency. */ + if (list_entry == NULL) { + ifp = (struct interface *)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++) { + adj = listnode_head( + circuit->u.bc.adjdb[level - 1]); + if (adj) + break; + } + break; + case CIRCUIT_T_P2P: + adj = circuit->u.p2p.neighbor; + break; + default: + adj = NULL; + break; + } + + return adj; + } + + /* Get next adjacency. */ + adj = (struct isis_adjacency *)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/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_enum(xpath, adj->level); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, sysid_print(adj->sysid)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint32(xpath, adj->circuit->circuit_id); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, snpa_print(adj->snpa)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint16(xpath, adj->hold_time); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state)); +} + /* * NOTIFICATIONS */ @@ -2545,19 +2725,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj, listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); - switch (new_state) { - case ISIS_ADJ_DOWN: - data = yang_data_new_string(xpath_arg, "down"); - break; - case ISIS_ADJ_UP: - data = yang_data_new_string(xpath_arg, "up"); - break; - case ISIS_ADJ_INITIALIZING: - data = yang_data_new_string(xpath_arg, "init"); - break; - default: - data = yang_data_new_string(xpath_arg, "failed"); - } + data = yang_data_new_string(xpath_arg, isis_yang_adj_state(new_state)); listnode_add(arguments, data); if (new_state == ISIS_ADJ_DOWN) { snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); @@ -3483,6 +3651,54 @@ const struct frr_yang_module_info frr_isisd_info = { .modify = lib_interface_isis_multi_topology_ipv6_dstsrc_modify, }, }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency", + .cbs = { + .get_next = lib_interface_isis_adjacencies_adjacency_get_next, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem, + } + }, { .xpath = NULL, }, diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index b0f395fea8..c724e1089b 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -61,6 +61,13 @@ module frr-isisd { "This type defines IS-IS level of an object."; } + typedef extended-circuit-id { + type uint32; + description + "This type defines the extended circuit ID + associated with an interface."; + } + typedef network-type { type enumeration { enum "unknown" { @@ -95,6 +102,20 @@ module frr-isisd { pattern, An example LSP ID is 0143.0438.AeF0.02-01"; } + typedef snpa { + type string { + length "0 .. 20"; + } + description + "This type defines the Subnetwork Point + of Attachment (SNPA) format. + The SNPA should be encoded according to the rules + specified for the particular type of subnetwork + being used. As an example, for an ethernet subnetwork, + the SNPA is encoded as a MAC address like + '00aa.bbcc.ddee'."; + } + typedef system-id { type string { pattern "[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}"; @@ -544,6 +565,70 @@ module frr-isisd { } } + grouping adjacency-state { + container adjacencies { + config false; + list adjacency { + leaf neighbor-sys-type { + type level; + description + "Level capability of neighboring system"; + } + leaf neighbor-sysid { + type system-id; + description + "The system-id of the neighbor"; + } + leaf neighbor-extended-circuit-id { + type extended-circuit-id; + description + "Circuit ID of the neighbor"; + } + leaf neighbor-snpa { + type snpa; + description + "SNPA of the neighbor"; + } + leaf hold-timer { + type uint16; + units seconds; + description + "The holding time in seconds for this + adjacency. This value is based on + received hello PDUs and the elapsed + time since receipt."; + } + leaf neighbor-priority { + type uint8 { + range "0 .. 127"; + } + description + "Priority of the neighboring IS for becoming + the DIS."; + } + leaf state { + type adj-state-type; + description + "This leaf describes the state of the interface."; + } + + description + "List of operational adjacencies."; + } + description + "This container lists the adjacencies of + the local node."; + } + description + "Adjacency state"; + } + + grouping interface-state { + description + "IS-IS interface operational state."; + uses adjacency-state; + } + grouping notification-instance-hdr { description "Instance specific IS-IS notification data grouping"; @@ -582,7 +667,7 @@ module frr-isisd { } leaf extended-circuit-id { - type uint32; + type extended-circuit-id; description "Eextended circuit-id of the interface."; } @@ -1003,6 +1088,7 @@ module frr-isisd { description "IS-IS interface parameters."; uses interface-config; + uses interface-state; } } From c32496ee5cbfba00cf449ed3218df3d2caee5c3f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 23 Sep 2019 09:38:02 -0300 Subject: [PATCH 3/3] isisd, yang: implement interface counters The new "event-counters" grouping is almost a 1:1 copy of the same grouping from the IETF IS-IS module, except for the "lan-dis-changes" leaf which was skipped (more work needs to be done to support it). Signed-off-by: Renato Westphal --- isisd/isis_adjacency.c | 1 + isisd/isis_circuit.h | 7 ++ isisd/isis_northbound.c | 247 ++++++++++++++++++++++++++++++++++++++++ isisd/isis_pdu.c | 33 +++++- yang/frr-isisd.yang | 60 ++++++++++ 5 files changed, 342 insertions(+), 6 deletions(-) diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 9b368cc404..d2ec6ff566 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -254,6 +254,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, reason ? reason : "unspecified"); } + circuit->adj_state_changes++; #ifndef FABRICD /* send northbound notification */ isis_notif_adj_state_change(adj, new_state, reason); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index e3541644aa..b77c8ce352 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -144,6 +144,13 @@ struct isis_circuit { uint32_t desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */ uint32_t rej_adjacencies; /* rejectedAdjacencies */ + /* + * Counters as in ietf-isis@2019-09-09.yang + */ + uint32_t id_len_mismatches; /* id-len-mismatch */ + uint32_t max_area_addr_mismatches; /* max-area-addresses-mismatch */ + uint32_t auth_type_failures; /*authentication-type-fails */ + uint32_t auth_failures; /* authentication-fails */ QOBJ_FIELDS }; diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index 7eba4791af..ccd4cfbd1c 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -2483,6 +2483,205 @@ lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state)); } +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_changes_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->adj_state_changes); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_number_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj; + struct listnode *node; + uint32_t total = 0; + + ifp = (struct interface *)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(xpath, total); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->init_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_rejects_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->rej_adjacencies); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch + */ +static struct yang_data * +lib_interface_isis_event_counters_id_len_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->id_len_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch + */ +static struct yang_data * +lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_authentication_type_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_type_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_authentication_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_failures); +} + /* * NOTIFICATIONS */ @@ -3699,6 +3898,54 @@ const struct frr_yang_module_info frr_isisd_info = { .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem, } }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_init_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem, + } + }, { .xpath = NULL, }, diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index ecfce392ff..46b013ddd0 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -576,6 +576,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (p2p_hello) { if (circuit->circ_type != CIRCUIT_T_P2P) { zlog_warn("p2p hello on non p2p circuit"); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "p2p hello on non p2p circuit", @@ -586,6 +587,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, } else { if (circuit->circ_type != CIRCUIT_T_BROADCAST) { zlog_warn("lan hello on non broadcast circuit"); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "lan hello on non broadcast circuit", @@ -598,6 +600,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, zlog_debug( "level %d LAN Hello received over circuit with externalDomain = true", level); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, @@ -614,6 +617,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, circuit->area->area_tag, circuit->interface->name); } + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Interface level mismatch", raw_pdu); @@ -643,6 +647,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, "ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16, circuit->area->area_tag, pdu_name, circuit->interface->name, iih.pdu_len); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency(circuit, "Invalid PDU length", raw_pdu); @@ -654,6 +659,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, flog_err(EC_ISIS_PACKET, "Level %d LAN Hello with Circuit Type %d", level, iih.circ_type); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "LAN Hello with wrong IS-level", raw_pdu); @@ -667,6 +673,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream), circuit->rcv_stream, &iih.tlvs, &error_log)) { zlog_warn("isis_unpack_tlvs() failed: %s", error_log); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency(circuit, "Failed to unpack TLVs", raw_pdu); @@ -685,6 +692,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (!iih.tlvs->protocols_supported.count) { zlog_warn("No supported protocols TLV in %s", pdu_name); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "No supported protocols TLV", raw_pdu); @@ -702,11 +710,14 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, /* send northbound notification */ stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, pdu_end - pdu_start); - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -715,6 +726,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, zlog_warn( "ISIS-Adj (%s): Received IIH with own sysid - discard", circuit->area->area_tag); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Received IIH with our own sysid", raw_pdu); @@ -752,6 +764,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, "ISIS-Adj (%s): Neither IPv4 nor IPv6 considered usable. Ignoring IIH", circuit->area->area_tag); } + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Neither IPv4 not IPv6 considered usable", @@ -940,11 +953,14 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, hdr.lsp_id); #ifndef FABRICD /* send northbound notification */ - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -1373,12 +1389,15 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, /* send northbound notification */ stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, pdu_end - pdu_start); - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -1614,6 +1633,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) "IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8 ", while the parameter for this IS is %u", id_len, ISIS_SYS_ID_LEN); + circuit->id_len_mismatches++; #ifndef FABRICD /* send northbound notification */ isis_notif_id_len_mismatch(circuit, id_len, raw_pdu); @@ -1666,6 +1686,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8 " while the parameter for this IS is %u", max_area_addrs, isis->max_area_addrs); + circuit->max_area_addr_mismatches++; #ifndef FABRICD /* send northbound notification */ isis_notif_max_area_addr_mismatch(circuit, max_area_addrs, diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index c724e1089b..faa880eff4 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -623,10 +623,70 @@ module frr-isisd { "Adjacency state"; } + grouping event-counters { + container event-counters { + config false; + leaf adjacency-changes { + type uint32; + description + "The number of times an adjacency state change has + occurred on this interface."; + } + leaf adjacency-number { + type uint32; + description + "The number of adjacencies on this interface."; + } + leaf init-fails { + type uint32; + description + "The number of times initialization of this + interface has failed. This counts events such + as PPP NCP failures. Failures to form an + adjacency are counted by adjacency-rejects."; + } + leaf adjacency-rejects { + type uint32; + description + "The number of times an adjacency has been + rejected on this interface."; + } + leaf id-len-mismatch { + type uint32; + description + "The number of times an IS-IS PDU with an ID + field length different from that for this + system has been received on this interface."; + } + leaf max-area-addresses-mismatch { + type uint32; + description + "The number of times an IS-IS PDU has been + received on this interface with the + max area address field differing from that of + this system."; + } + leaf authentication-type-fails { + type uint32; + description + "Number of authentication type mismatches."; + } + leaf authentication-fails { + type uint32; + description + "Number of authentication key failures."; + } + description "IS-IS interface event counters."; + } + description + "Grouping for IS-IS interface event counters"; + } + grouping interface-state { description "IS-IS interface operational state."; uses adjacency-state; + uses event-counters; } grouping notification-instance-hdr {