/* * Add this IS to the root of SPT */ static void isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area, int level) { struct isis_vertex *vertex; struct isis_lsp *lsp; u_char lspid[ISIS_SYS_ID_LEN + 2]; memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (lspid) = 0; LSP_FRAGMENT (lspid) = 0; lsp = lsp_search (lspid, area->lspdb[level - 1]); if (lsp == NULL) Log(LOG_WARNING, "WARN ( default/core/ISIS ): ISIS-Spf: could not find own l%d LSP!\n", level); if (!area->oldmetric) vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS); else vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS); vertex->lsp = lsp; listnode_add (spftree->paths, vertex); return; }
/* * Find the system LSP: returns the LSP in our LSP database * associated with the given system ID. */ static struct isis_lsp * isis_root_system_lsp (struct isis_area *area, int level, u_char *sysid) { struct isis_lsp *lsp; u_char lspid[ISIS_SYS_ID_LEN + 2]; memcpy (lspid, sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (lspid) = 0; LSP_FRAGMENT (lspid) = 0; lsp = lsp_search (lspid, area->lspdb[level - 1]); if (lsp && lsp->lsp_header->rem_lifetime != 0) return lsp; return NULL; }
/* * Add this IS to the root of SPT */ static void isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area, int level) { struct isis_vertex *vertex; struct isis_lsp *lsp; u_char lspid[ISIS_SYS_ID_LEN + 2]; #ifdef EXTREME_DEBUG u_char buff[BUFSIZ]; #endif /* EXTREME_DEBUG */ memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID (lspid) = 0; LSP_FRAGMENT (lspid) = 0; lsp = lsp_search (lspid, area->lspdb[level - 1]); if (lsp == NULL) zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level); if (!area->oldmetric) vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS); else vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS); vertex->lsp = lsp; listnode_add (spftree->paths, vertex); #ifdef EXTREME_DEBUG zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", vtype2string (vertex->type), vid2string (vertex, buff), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ return; }
/* * C.2.6 Step 1 */ static int isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint32_t cost, uint16_t depth, int family) { struct listnode *node, *fragnode = NULL; u_int16_t dist; struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; struct ipv4_reachability *ipreach; struct te_ipv4_reachability *te_ipv4_reach; enum vertextype vtype; struct prefix prefix; #ifdef HAVE_IPV6 struct ipv6_reachability *ip6reach; #endif /* HAVE_IPV6 */ if (!lsp->adj) return ISIS_WARNING; if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) return ISIS_OK; lspfragloop: if (lsp->lsp_header->seq_num == 0) { zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num" " - do not process"); return ISIS_WARNING; } if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) { if (lsp->tlv_data.is_neighs) { for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) { /* C.2.6 a) */ /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; dist = cost + is_neigh->metrics.metric_default; vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (lsp->tlv_data.te_is_neighs) { for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) { uint32_t metric; if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; memcpy (&metric, te_is_neigh->te_metric, 3); dist = cost + ntohl (metric << 8); vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) { prefix.family = AF_INET; for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_INTERNAL; prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) { prefix.family = AF_INET; for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_EXTERNAL; prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } }