diff options
author | lynne <lynne@voltanet.io> | 2021-01-30 01:36:22 +0100 |
---|---|---|
committer | lynne <lynne@voltanet.io> | 2021-02-01 22:04:10 +0100 |
commit | 77d73edfcd5753580e9d1b6b131e6c83890d19d6 (patch) | |
tree | 5082ba7feb1bd4391601f44e805e5fc0044f462f /isisd | |
parent | Merge pull request #7953 from mjstapp/fix_more_ntoa (diff) | |
download | frr-77d73edfcd5753580e9d1b6b131e6c83890d19d6.tar.xz frr-77d73edfcd5753580e9d1b6b131e6c83890d19d6.zip |
isisd: When adjacencies go up and down add support to modify attached-bit
When adjacencies change state the attached-bits in LSPs in other areas
on the router may need to be modified.
1. If a router no longer has a L2 adjacency to another area the
attached-bit must no longer be sent in the LSP
2. If a new L2 adjacency comes up in a different area then the
attached-bit should be sent in the LSP
Signed-off-by: Lynne Morrison <lynne@voltanet.io>
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/isis_lsp.c | 78 | ||||
-rw-r--r-- | isisd/isis_spf.c | 12 | ||||
-rw-r--r-- | isisd/isisd.c | 16 | ||||
-rw-r--r-- | isisd/isisd.h | 1 |
4 files changed, 90 insertions, 17 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 4c70bd12b..6d2303817 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -417,22 +417,18 @@ static bool isis_level2_adj_up(struct isis_area *curr_area) 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) { - for (ALL_LIST_ELEMENTS_RO(adjdb, node, - adj)) - if ((adj->level - == ISIS_ADJ_LEVEL2 - || adj->level - == ISIS_ADJ_LEVEL1AND2) - && adj->adj_state - == ISIS_ADJ_UP) - return true; + 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; - if ((adj->level == ISIS_ADJ_LEVEL2 - || adj->level == ISIS_ADJ_LEVEL1AND2) + if (adj->level != ISIS_ADJ_LEVEL1 && adj->adj_state == ISIS_ADJ_UP) return true; } @@ -441,6 +437,58 @@ static bool isis_level2_adj_up(struct isis_area *curr_area) return false; } +static void isis_reset_attach_bit(struct isis_adjacency *curr_adj) +{ + struct listnode *node; + struct isis_area *curr_area = curr_adj->circuit->area; + struct isis *isis = curr_area->isis; + struct isis_area *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 (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->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); + + 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); + } + } +} + static uint8_t lsp_bits_generate(int level, int overload_bit, int attached_bit, struct isis_area *area) { @@ -2087,6 +2135,12 @@ void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit, static int lsp_handle_adj_state_change(struct isis_adjacency *adj) { lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + + /* when an adjacency state changes determine if we need to + * change attach_bits in other area's LSPs + */ + isis_reset_attach_bit(adj); + return 0; } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index ec0313f21..22dfee994 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1047,15 +1047,17 @@ lspfragloop: end: - /* if attach bit set and we are a level-1 router - * and attach-bit-rcv-ignore is not configured - * add a default route toward this neighbor + /* if attach bit set in LSP, attached-bit receive ignore is + * not configured, we are a level-1 area and we have no other + * level-2 | level1-2 areas then add a default route toward + * this neighbor */ if ((lsp->hdr.lsp_bits & LSPBIT_ATT) == LSPBIT_ATT && !spftree->area->attached_bit_rcv_ignore - && spftree->area->is_type == IS_LEVEL_1) { + && spftree->area->is_type == IS_LEVEL_1 + && !isis_area_count(spftree->area->isis, IS_LEVEL_2)) { struct prefix_pair ip_info = { {0} }; - if (IS_DEBUG_SPF_EVENTS) + if (IS_DEBUG_RTE_EVENTS) zlog_debug("ISIS-Spf (%s): add default %s route", rawlspid_print(lsp->hdr.lsp_id), spftree->family == AF_INET ? "ipv4" diff --git a/isisd/isisd.c b/isisd/isisd.c index d45690f4d..a802bac13 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -424,6 +424,22 @@ 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 a09f74152..22d9c6236 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -243,6 +243,7 @@ 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); |