summaryrefslogtreecommitdiffstats
path: root/isisd
diff options
context:
space:
mode:
authorlynne <lynne@voltanet.io>2021-01-30 01:36:22 +0100
committerlynne <lynne@voltanet.io>2021-02-01 22:04:10 +0100
commit77d73edfcd5753580e9d1b6b131e6c83890d19d6 (patch)
tree5082ba7feb1bd4391601f44e805e5fc0044f462f /isisd
parentMerge pull request #7953 from mjstapp/fix_more_ntoa (diff)
downloadfrr-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.c78
-rw-r--r--isisd/isis_spf.c12
-rw-r--r--isisd/isisd.c16
-rw-r--r--isisd/isisd.h1
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);