diff options
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/isis_adjacency.c | 1 | ||||
-rw-r--r-- | isisd/isis_circuit.c | 49 | ||||
-rw-r--r-- | isisd/isis_circuit.h | 9 | ||||
-rw-r--r-- | isisd/isis_cli.c | 111 | ||||
-rw-r--r-- | isisd/isis_main.c | 2 | ||||
-rw-r--r-- | isisd/isis_northbound.c | 534 | ||||
-rw-r--r-- | isisd/isis_pdu.c | 35 | ||||
-rw-r--r-- | isisd/isis_te.c | 3 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 79 | ||||
-rw-r--r-- | isisd/isis_zebra.h | 2 | ||||
-rw-r--r-- | isisd/isisd.c | 3 | ||||
-rw-r--r-- | isisd/isisd.h | 3 |
12 files changed, 633 insertions, 198 deletions
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 9b368cc40..d2ec6ff56 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.c b/isisd/isis_circuit.c index 5da8e6ee9..29fb725b0 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -61,6 +61,8 @@ DEFINE_QOBJ_TYPE(isis_circuit) +DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)) + /* * Prototypes. */ @@ -1389,6 +1391,51 @@ int isis_if_delete_hook(struct interface *ifp) return 0; } +static int isis_ifp_create(struct interface *ifp) +{ + if (if_is_operative(ifp)) + isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), + ifp); + + hook_call(isis_if_new_hook, ifp); + + return 0; +} + +static int isis_ifp_up(struct interface *ifp) +{ + isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + + return 0; +} + +static int isis_ifp_down(struct interface *ifp) +{ + struct isis_circuit *circuit; + + circuit = isis_csm_state_change(IF_DOWN_FROM_Z, + circuit_scan_by_ifp(ifp), ifp); + if (circuit) + SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); + + return 0; +} + +static int isis_ifp_destroy(struct interface *ifp) +{ + if (if_is_operative(ifp)) + zlog_warn("Zebra: got delete of %s, but interface is still up", + ifp->name); + + isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + + /* Cannot call if_delete because we should retain the pseudo interface + in case there is configuration info attached to it. */ + if_delete_retain(ifp); + + return 0; +} + void isis_circuit_init(void) { /* Initialize Zebra interface data structure */ @@ -1398,4 +1445,6 @@ void isis_circuit_init(void) /* Install interface node */ install_node(&interface_node, isis_interface_config_write); if_cmd_init(); + if_zapi_callbacks(isis_ifp_create, isis_ifp_up, + isis_ifp_down, isis_ifp_destroy); } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index e3541644a..f677d3ade 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -32,6 +32,8 @@ #include "isis_constants.h" #include "isis_common.h" +DECLARE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)); + struct isis_lsp; struct password { @@ -144,6 +146,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_cli.c b/isisd/isis_cli.c index bd0628675..37f4dcfab 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -188,14 +188,10 @@ DEFPY(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", } /* check if the interface is a loopback and if so set it as passive */ - pthread_rwlock_rdlock(&running_config->lock); - { - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (ifp && if_is_loopback(ifp)) - nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", - NB_OP_MODIFY, "true"); - } - pthread_rwlock_unlock(&running_config->lock); + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + if (ifp && if_is_loopback(ifp)) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", + NB_OP_MODIFY, "true"); return nb_cli_apply_changes(vty, NULL); } @@ -262,14 +258,10 @@ DEFPY(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", } /* check if the interface is a loopback and if so set it as passive */ - pthread_rwlock_rdlock(&running_config->lock); - { - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (ifp && if_is_loopback(ifp)) - nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", - NB_OP_MODIFY, "true"); - } - pthread_rwlock_unlock(&running_config->lock); + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + if (ifp && if_is_loopback(ifp)) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", + NB_OP_MODIFY, "true"); return nb_cli_apply_changes(vty, NULL); } @@ -410,26 +402,20 @@ DEFPY(no_is_type, no_is_type_cmd, "Act as both a station router and an area router\n" "Act as an area router only\n") { - const char *value; - - pthread_rwlock_rdlock(&running_config->lock); - { - struct isis_area *area; + const char *value = NULL; + struct isis_area *area; - area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - - /* - * Put the is-type back to defaults: - * - level-1-2 on first area - * - level-1 for the rest - */ - if (area && listgetdata(listhead(isis->area_list)) == area) - value = "level-1-2"; - else - value = NULL; - } - pthread_rwlock_unlock(&running_config->lock); + area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + /* + * Put the is-type back to defaults: + * - level-1-2 on first area + * - level-1 for the rest + */ + if (area && listgetdata(listhead(isis->area_list)) == area) + value = "level-1-2"; + else + value = NULL; nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); @@ -1817,45 +1803,52 @@ DEFPY(no_isis_circuit_type, no_isis_circuit_type_cmd, "Level-1-2 adjacencies are formed\n" "Level-2 only adjacencies are formed\n") { - const char *circ_type = NULL; + struct interface *ifp; + struct isis_circuit *circuit; + int is_type; + const char *circ_type; /* * Default value depends on whether the circuit is part of an area, * and the is-type of the area if there is one. So we need to do this * here. */ - pthread_rwlock_rdlock(&running_config->lock); - { - struct interface *ifp; - struct isis_circuit *circuit; + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); + if (!ifp) + goto def_val; - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (!ifp) - goto unlock; + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + goto def_val; - circuit = circuit_scan_by_ifp(ifp); - if (!circuit || circuit->state != C_STATE_UP) - goto unlock; + if (circuit->state == C_STATE_UP) + is_type = circuit->area->is_type; + else + goto def_val; - switch (circuit->area->is_type) { - case IS_LEVEL_1: - circ_type = "level-1"; - break; - case IS_LEVEL_2: - circ_type = "level-2"; - break; - case IS_LEVEL_1_AND_2: - circ_type = "level-1-2"; - break; - } + switch (is_type) { + case IS_LEVEL_1: + circ_type = "level-1"; + break; + case IS_LEVEL_2: + circ_type = "level-2"; + break; + case IS_LEVEL_1_AND_2: + circ_type = "level-1-2"; + break; + default: + return CMD_ERR_NO_MATCH; } -unlock: - pthread_rwlock_unlock(&running_config->lock); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, circ_type); return nb_cli_apply_changes(vty, NULL); + +def_val: + nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); } void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode, diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 7f49e9d89..718924daf 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -243,7 +243,7 @@ int main(int argc, char **argv, char **envp) mt_init(); /* create the global 'isis' instance */ - isis_new(1); + isis_new(1, VRF_DEFAULT); isis_zebra_init(master); isis_bfd_init(); diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index bd6191869..97b7ae4f7 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -49,6 +49,23 @@ #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 */ static int isis_instance_create(enum nb_event event, @@ -1401,29 +1418,12 @@ static int isis_instance_mpls_te_create(enum nb_event event, area->mta->status = enable; } - /* - * Following code is intended to handle two cases; - * - * 1) MPLS-TE was disabled at startup time, but now become enabled. - * In this case, we must enable MPLS-TE Circuit regarding interface - * MPLS_TE flag - * 2) MPLS-TE was once enabled then disabled, and now enabled again. - */ - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { - if (circuit->ext == NULL) - continue; + /* Update Extended TLVs according to Interface link parameters */ + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_link_params_update(circuit, circuit->interface); - if (!IS_EXT_TE(circuit->ext) - && HAS_LINK_PARAMS(circuit->interface)) - isis_link_params_update(circuit, circuit->interface); - else - continue; - - /* Reoriginate STD_TE & GMPLS circuits */ - if (circuit->area) - lsp_regenerate_schedule(circuit->area, circuit->is_type, - 0); - } + /* Reoriginate STD_TE & GMPLS circuits */ + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -1456,13 +1456,11 @@ static int isis_instance_mpls_te_destroy(enum nb_event event, circuit->ext->status = EXT_LAN_ADJ_SID; else circuit->ext->status = 0; - - /* Re-originate circuit without STD_TE & GMPLS parameters */ - if (circuit->area) - lsp_regenerate_schedule(circuit->area, circuit->is_type, - 0); } + /* Reoriginate STD_TE & GMPLS circuits */ + lsp_regenerate_schedule(area, area->is_type, 0); + zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering", area->area_tag); @@ -1492,8 +1490,7 @@ static int isis_instance_mpls_te_router_address_modify(enum nb_event event, area->mta->router_id.s_addr = value.s_addr; /* And re-schedule LSP update */ - if (listcount(area->area_addrs) > 0) - lsp_regenerate_schedule(area, area->is_type, 0); + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -1515,8 +1512,7 @@ static int isis_instance_mpls_te_router_address_destroy(enum nb_event event, area->mta->router_id.s_addr = INADDR_ANY; /* And re-schedule LSP update */ - if (listcount(area->area_addrs) > 0) - lsp_regenerate_schedule(area, area->is_type, 0); + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -1542,9 +1538,9 @@ static int lib_interface_isis_create(enum nb_event event, /* check if interface mtu is sufficient. If the area has not * been created yet, assume default MTU for the area */ - ifp = nb_running_get_entry(dnode, NULL, true); + ifp = nb_running_get_entry(dnode, NULL, false); /* zebra might not know yet about the MTU - nothing we can do */ - if (ifp->mtu == 0) + if (!ifp || ifp->mtu == 0) break; actual_mtu = if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; @@ -2304,6 +2300,368 @@ static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( } /* + * 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)); +} + +/* + * 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 */ static void notif_prep_instance_hdr(const char *xpath, @@ -2545,19 +2903,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); @@ -3484,6 +3830,102 @@ const struct frr_yang_module_info frr_isisd_info = { }, }, { + .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 = "/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 ecfce392f..a637ff003 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -187,7 +187,7 @@ static int process_p2p_hello(struct iih_info *iih) adj->sys_type = ISIS_SYSTYPE_UNKNOWN; } - if (tw_adj && adj->threeway_state == ISIS_THREEWAY_DOWN) + if (tw_adj) adj->ext_circuit_id = tw_adj->local_circuit_id; /* 8.2.6 Monitoring point-to-point adjacencies */ @@ -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/isisd/isis_te.c b/isisd/isis_te.c index 44fa45d02..9871d2bcb 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -81,8 +81,7 @@ void isis_link_params_update(struct isis_circuit *circuit, return; /* Sanity Check */ - if ((circuit == NULL) || (ifp == NULL) - || (circuit->state != C_STATE_UP)) + if ((ifp == NULL) || (circuit->state != C_STATE_UP)) return; zlog_debug("TE(%s): Update circuit parameters for interface %s", diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 39a2f6ef3..bdf6869f5 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -53,8 +53,6 @@ struct zclient *zclient = NULL; -DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)) - /* Router-id update message from zebra. */ static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS) { @@ -74,79 +72,6 @@ static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS) return 0; } -static int isis_zebra_if_add(ZAPI_CALLBACK_ARGS) -{ - struct interface *ifp; - - ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - - if (if_is_operative(ifp)) - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), - ifp); - - hook_call(isis_if_new_hook, ifp); - - return 0; -} - -static int isis_zebra_if_del(ZAPI_CALLBACK_ARGS) -{ - struct interface *ifp; - struct stream *s; - - s = zclient->ibuf; - ifp = zebra_interface_state_read(s, vrf_id); - - if (!ifp) - return 0; - - if (if_is_operative(ifp)) - zlog_warn("Zebra: got delete of %s, but interface is still up", - ifp->name); - - isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); - - /* Cannot call if_delete because we should retain the pseudo interface - in case there is configuration info attached to it. */ - if_delete_retain(ifp); - - if_set_index(ifp, IFINDEX_INTERNAL); - - return 0; -} - -static int isis_zebra_if_state_up(ZAPI_CALLBACK_ARGS) -{ - struct interface *ifp; - - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - - if (ifp == NULL) - return 0; - - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); - - return 0; -} - -static int isis_zebra_if_state_down(ZAPI_CALLBACK_ARGS) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - - if (ifp == NULL) - return 0; - - circuit = isis_csm_state_change(IF_DOWN_FROM_Z, - circuit_scan_by_ifp(ifp), ifp); - if (circuit) - SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); - - return 0; -} - static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS) { struct connected *c; @@ -388,10 +313,6 @@ void isis_zebra_init(struct thread_master *master) zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs); zclient->zebra_connected = isis_zebra_connected; zclient->router_id_update = isis_router_id_update_zebra; - zclient->interface_add = isis_zebra_if_add; - zclient->interface_delete = isis_zebra_if_del; - zclient->interface_up = isis_zebra_if_state_up; - zclient->interface_down = isis_zebra_if_state_down; zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_delete = isis_zebra_if_address_del; zclient->interface_link_params = isis_zebra_link_params; diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index 83a32108e..d00f348c8 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -24,8 +24,6 @@ extern struct zclient *zclient; -DECLARE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)); - void isis_zebra_init(struct thread_master *); void isis_zebra_stop(void); diff --git a/isisd/isisd.c b/isisd/isisd.c index 67f557ab5..029a9e068 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -75,12 +75,13 @@ int clear_isis_neighbor_common(struct vty *, const char *id); int isis_config_write(struct vty *); -void isis_new(unsigned long process_id) +void isis_new(unsigned long process_id, vrf_id_t vrf_id) { isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); /* * Default values */ + isis->vrf_id = vrf_id; isis->max_area_addrs = 3; isis->process_id = process_id; isis->router_id = 0; diff --git a/isisd/isisd.h b/isisd/isisd.h index 308f018c1..f825b6ecb 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -62,6 +62,7 @@ extern struct zebra_privs_t isisd_privs; struct fabricd; struct isis { + vrf_id_t vrf_id; unsigned long process_id; int sysid_set; uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ @@ -189,7 +190,7 @@ struct isis_area { DECLARE_QOBJ_TYPE(isis_area) void isis_init(void); -void isis_new(unsigned long); +void isis_new(unsigned long process_id, vrf_id_t vrf_id); struct isis_area *isis_area_create(const char *); struct isis_area *isis_area_lookup(const char *); int isis_area_get(struct vty *vty, const char *area_tag); |