Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isisd: fix setting of the attached bit (backport #9024) #9147

Merged
merged 3 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 44 additions & 60 deletions isisd/isis_lsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,101 +401,85 @@ static void lsp_seqno_update(struct isis_lsp *lsp0)
return;
}

static bool isis_level2_adj_up(struct isis_area *curr_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;
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;
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];
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);
}
}

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;
Expand Down
2 changes: 2 additions & 0 deletions isisd/isis_lsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions isisd/isis_spf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 0 additions & 16 deletions isisd/isisd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion isisd/isisd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down