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);
}
}
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;
if (area->dynhostname && lsp->tlvs->hostname
&& lsp->hdr.rem_lifetime) {
- isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname,
- (lsp->hdr.lsp_bits & LSPBIT_IST)
- == IS_LEVEL_1_AND_2
- ? IS_LEVEL_2
- : IS_LEVEL_1);
+ isis_dynhn_insert(
+ area->isis, lsp->hdr.lsp_id, lsp->tlvs->hostname,
+ (lsp->hdr.lsp_bits & LSPBIT_IST) == IS_LEVEL_1_AND_2
+ ? IS_LEVEL_2
+ : IS_LEVEL_1);
}
return;
}
/*
- * Build a list of LSPs with non-zero ht bounded by start and stop ids
+ * Build a list of LSPs with non-zero ht and seqno bounded by start and stop ids
*/
void lsp_build_list_nonzero_ht(struct lspdb_head *head, const uint8_t *start_id,
const uint8_t *stop_id, struct list *list)
ISIS_SYS_ID_LEN + 2) > 0)
break;
- if (lsp->hdr.rem_lifetime)
+ if (lsp->hdr.rem_lifetime && lsp->hdr.seqno)
listnode_add(list, lsp);
}
}
char id[SYSID_STRLEN];
if (dynhost)
- dyn = dynhn_find_by_id(lsp_id);
+ dyn = dynhn_find_by_id(isis, lsp_id);
else
dyn = NULL;
area->area_tag);
}
+ if (IS_MPLS_TE(area->mta)
+ && !IN6_IS_ADDR_UNSPECIFIED(&area->mta->router_id_ipv6)) {
+ lsp_debug("ISIS (%s): Adding IPv6 TE Router ID tlv.",
+ area->area_tag);
+ isis_tlvs_set_te_router_id_ipv6(lsp->tlvs,
+ &area->mta->router_id_ipv6);
+ }
+
lsp_debug("ISIS (%s): Adding circuit specific information.",
area->area_tag);
struct list *adj_list;
struct listnode *node;
struct isis_area *area = circuit->area;
+ uint16_t mtid;
lsp_clear_data(lsp);
lsp->tlvs = isis_alloc_tlvs();
LSP_PSEUDO_ID(ne_id));
}
if (circuit->area->newmetric) {
- isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST,
- ne_id, 0, NULL);
+ if (area_is_mt(circuit->area))
+ mtid = ISIS_MT_IPV4_UNICAST;
+ else
+ mtid = ISIS_MT_DISABLE;
+ isis_tlvs_add_extended_reach(lsp->tlvs, mtid, ne_id, 0, NULL);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
area->area_tag, sysid_print(ne_id),