From 74ef8dd96158b3e0898a323d893f74449e0a412a Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Mon, 12 Jul 2021 23:51:27 +0300 Subject: [PATCH 1/3] isisd: fix setting of the attached bit Current code related to setting of the attached bit checks for existence of L2 adjacencies in other routers configured on the device. This makes no sense. We should check for L2 adjacencies in the same router where we have L1 adjacencies. Signed-off-by: Igor Ryzhov --- isisd/isis_lsp.c | 101 +++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 814ba8fc2a..87a6061d4e 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -401,93 +401,74 @@ static void lsp_seqno_update(struct isis_lsp *lsp0) return; } -static bool isis_level2_adj_up(struct isis_area *curr_area) +static bool isis_level2_adj_up(struct isis_area *area) { struct listnode *node, *cnode; struct isis_circuit *circuit; struct list *adjdb; struct isis_adjacency *adj; - struct isis *isis = curr_area->isis; - struct isis_area *area; - /* lookup for a Level2 adjacency up in another area */ - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - if (area->area_tag - && strcmp(area->area_tag, curr_area->area_tag) == 0) - continue; + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + adjdb = circuit->u.bc.adjdb[1]; + if (!adjdb || !adjdb->count) + continue; - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { - if (circuit->circ_type == CIRCUIT_T_BROADCAST) { - adjdb = circuit->u.bc.adjdb[1]; - if (!adjdb || !adjdb->count) - continue; - - for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { - if (adj->level != ISIS_ADJ_LEVEL1 - && adj->adj_state == ISIS_ADJ_UP) - return true; - } - } else if (circuit->circ_type == CIRCUIT_T_P2P - && circuit->u.p2p.neighbor) { - adj = circuit->u.p2p.neighbor; + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { if (adj->level != ISIS_ADJ_LEVEL1 && adj->adj_state == ISIS_ADJ_UP) return true; } + } else if (circuit->circ_type == CIRCUIT_T_P2P + && circuit->u.p2p.neighbor) { + adj = circuit->u.p2p.neighbor; + if (adj->level != ISIS_ADJ_LEVEL1 + && adj->adj_state == ISIS_ADJ_UP) + return true; } } + return false; } -static void isis_reset_attach_bit(struct isis_adjacency *curr_adj) +static void isis_reset_attach_bit(struct isis_adjacency *adj) { - struct listnode *node; - struct isis_area *curr_area = curr_adj->circuit->area; - struct isis *isis = curr_area->isis; - struct isis_area *area; + struct isis_area *area = adj->circuit->area; struct lspdb_head *head; struct isis_lsp *lsp; uint8_t lspid[ISIS_SYS_ID_LEN + 2]; - /* If new adjaceny is up and area is level2 or level1and2 verify if - * we have LSPs in other areas that should now set the attach bit. - * - * If adjacenty is down, verify if we no longer have another level2 - * or level1and2 areas so that we should now remove the attach bit. + /* + * If an L2 adjacency changed its state in L-1-2 area, we have to: + * - set the attached bit in L1 LSPs if it's the first L2 adjacency + * - remove the attached bit in L1 LSPs if it's the last L2 adjacency */ - if (curr_area->is_type == IS_LEVEL_1) + + if (area->is_type != IS_LEVEL_1_AND_2 || adj->level == ISIS_ADJ_LEVEL1) return; - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - if (area->area_tag - && strcmp(area->area_tag, curr_area->area_tag) == 0) - continue; + if (!area->attached_bit_send) + return; - if (!area->attached_bit_send) - continue; + head = &area->lspdb[IS_LEVEL_1 - 1]; + memset(lspid, 0, ISIS_SYS_ID_LEN + 2); + memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN); - head = &area->lspdb[IS_LEVEL_1 - 1]; - memset(lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN); + lsp = lsp_search(head, lspid); + if (!lsp) + return; - lsp = lsp_search(head, lspid); - if (!lsp) - continue; - - if (curr_adj->adj_state == ISIS_ADJ_UP - && !(lsp->hdr.lsp_bits & LSPBIT_ATT)) { - sched_debug( - "ISIS (%s): adj going up regenerate lsp-bits", - area->area_tag); - lsp_regenerate_schedule(area, IS_LEVEL_1, 0); - } else if (curr_adj->adj_state == ISIS_ADJ_DOWN - && lsp->hdr.lsp_bits & LSPBIT_ATT - && !isis_level2_adj_up(area)) { - sched_debug( - "ISIS (%s): adj going down regenerate lsp-bits", - area->area_tag); - lsp_regenerate_schedule(area, IS_LEVEL_1, 0); - } + if (adj->adj_state == ISIS_ADJ_UP + && !(lsp->hdr.lsp_bits & LSPBIT_ATT)) { + sched_debug("ISIS (%s): adj going up regenerate lsp-bits", + area->area_tag); + lsp_regenerate_schedule(area, IS_LEVEL_1, 0); + } else if (adj->adj_state == ISIS_ADJ_DOWN + && (lsp->hdr.lsp_bits & LSPBIT_ATT) + && !isis_level2_adj_up(area)) { + sched_debug("ISIS (%s): adj going down regenerate lsp-bits", + area->area_tag); + lsp_regenerate_schedule(area, IS_LEVEL_1, 0); } } From a4777e465ab5515bf36ad5f3dc4c413adf9d15b6 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Mon, 12 Jul 2021 23:56:04 +0300 Subject: [PATCH 2/3] isisd: fix processing of the attached bit There are two problems with the current code for processing the attached bit: - we should process it when acting both a level-1-only and level-1-2 - we should add the default route when we don't have L2 adjacensies, not when we don't have other routers configured on the device Signed-off-by: Igor Ryzhov --- isisd/isis_lsp.c | 5 ++++- isisd/isis_lsp.h | 2 ++ isisd/isis_spf.c | 4 ++-- isisd/isisd.c | 16 ---------------- isisd/isisd.h | 1 - 5 files changed, 8 insertions(+), 20 deletions(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 87a6061d4e..c0b74a9044 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -401,13 +401,16 @@ static void lsp_seqno_update(struct isis_lsp *lsp0) return; } -static bool isis_level2_adj_up(struct isis_area *area) +bool isis_level2_adj_up(struct isis_area *area) { struct listnode *node, *cnode; struct isis_circuit *circuit; struct list *adjdb; struct isis_adjacency *adj; + if (area->is_type == IS_LEVEL_1) + return false; + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { if (circuit->circ_type == CIRCUIT_T_BROADCAST) { adjdb = circuit->u.bc.adjdb[1]; diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index f3d9f61bcf..cac5f0d733 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -77,6 +77,8 @@ int _lsp_regenerate_schedule(struct isis_area *area, int level, int lsp_generate_pseudo(struct isis_circuit *circuit, int level); int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level); +bool isis_level2_adj_up(struct isis_area *area); + struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, uint16_t rem_lifetime, uint32_t seq_num, uint8_t lsp_bits, uint16_t checksum, diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 3e8ec8817e..45e89897ff 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1070,8 +1070,8 @@ end: */ if ((lsp->hdr.lsp_bits & LSPBIT_ATT) == LSPBIT_ATT && !spftree->area->attached_bit_rcv_ignore - && spftree->area->is_type == IS_LEVEL_1 - && !isis_area_count(spftree->area->isis, IS_LEVEL_2)) { + && (spftree->area->is_type & IS_LEVEL_1) + && !isis_level2_adj_up(spftree->area)) { struct prefix_pair ip_info = { {0} }; if (IS_DEBUG_RTE_EVENTS) zlog_debug("ISIS-Spf (%s): add default %s route", diff --git a/isisd/isisd.c b/isisd/isisd.c index 6c1308af0a..43efa0164d 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -469,22 +469,6 @@ int isis_area_get(struct vty *vty, const char *area_tag) return CMD_SUCCESS; } -/* return the number of Level1 and level-1-2 routers or - * the number of Level2 and level-1-2 routers configured - */ -int isis_area_count(const struct isis *isis, int levels) -{ - struct isis_area *area; - struct listnode *node; - int count = 0; - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) - if (area->is_type & levels) - count++; - - return count; -} - void isis_area_destroy(struct isis_area *area) { struct listnode *node, *nnode; diff --git a/isisd/isisd.h b/isisd/isisd.h index 60dcf066dd..64fbf78a07 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -269,7 +269,6 @@ struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id); struct isis_area *isis_area_lookup_by_vrf(const char *area_tag, const char *vrf_name); int isis_area_get(struct vty *vty, const char *area_tag); -int isis_area_count(const struct isis *isis, int levels); void isis_area_destroy(struct isis_area *area); void isis_filter_update(struct access_list *access); void isis_prefix_list_update(struct prefix_list *plist); From d0f1492145b68643fb8a2b31307d91e1139e3cfa Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Mon, 12 Jul 2021 23:56:50 +0300 Subject: [PATCH 3/3] isisd: fix setting IS type in LSPs IS type in an LSP is a type of the router, not a type of the circuit. Signed-off-by: Igor Ryzhov --- isisd/isis_lsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index c0b74a9044..5c013d634b 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -479,7 +479,7 @@ static uint8_t lsp_bits_generate(int level, int overload_bit, int attached_bit, struct isis_area *area) { uint8_t lsp_bits = 0; - if (level == IS_LEVEL_1) + if (area->is_type == IS_LEVEL_1) lsp_bits = IS_LEVEL_1; else lsp_bits = IS_LEVEL_1_AND_2;