From 0a6e7a5a3ffd662ccb1bf3474045ef80b007e16c 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 (cherry picked from commit 74ef8dd96158b3e0898a323d893f74449e0a412a) --- 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 814ba8fc2a13..87a6061d4e23 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) - 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->is_type != IS_LEVEL_1_AND_2 || adj->level == ISIS_ADJ_LEVEL1) + return; - if (!area->attached_bit_send) - continue; + if (!area->attached_bit_send) + return; - 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) - continue; + lsp = lsp_search(head, lspid); + if (!lsp) + return; - 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 180c0d0e64c16c3b5c2a31755538b544ac3dddb9 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 (cherry picked from commit a4777e465ab5515bf36ad5f3dc4c413adf9d15b6) --- 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 87a6061d4e23..c0b74a9044f4 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 f3d9f61bcfa4..cac5f0d73388 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 3e8ec8817e7e..45e89897ffa4 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1070,8 +1070,8 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, */ 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 7e78e0ce69da..1537fcb8ac08 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 b2c9af55b78f..f815969b9293 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 32839ccd54fcd714ac95e42c184d5525bdd54b42 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 (cherry picked from commit d0f1492145b68643fb8a2b31307d91e1139e3cfa) --- 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 c0b74a9044f4..5c013d634b72 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;