summaryrefslogtreecommitdiffstats
path: root/isisd/isis_spf.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_spf.c')
-rw-r--r--isisd/isis_spf.c235
1 files changed, 119 insertions, 116 deletions
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 615c2eeaa..ffe6bf2fb 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -44,7 +44,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
-#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_dynhn.h"
@@ -52,9 +51,24 @@
#include "isis_route.h"
#include "isis_csm.h"
#include "isis_mt.h"
+#include "isis_tlvs2.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
+/*
+ * supports the given af ?
+ */
+static bool speaks(uint8_t *protocols, uint8_t count, int family)
+{
+ for (uint8_t i = 0; i < count; i++) {
+ if (family == AF_INET && protocols[i] == NLPID_IP)
+ return true;
+ if (family == AF_INET6 && protocols[i] == NLPID_IPV6)
+ return true;
+ }
+ return false;
+}
+
struct isis_spf_run {
struct isis_area *area;
int level;
@@ -340,7 +354,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level,
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)
+ if (lsp && lsp->hdr.rem_lifetime != 0)
return lsp;
return NULL;
}
@@ -546,6 +560,13 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
assert(spftree && parent);
+ struct prefix p;
+ if (vtype >= VTYPE_IPREACH_INTERNAL) {
+ prefix_copy(&p, id);
+ apply_mask(&p);
+ id = &p;
+ }
+
/* RFC3787 section 5.1 */
if (spftree->area->newmetric == 1) {
if (dist > MAX_WIDE_PATH_METRIC)
@@ -632,30 +653,29 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
uint16_t depth, u_char *root_sysid,
struct isis_vertex *parent)
{
- bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id);
- struct listnode *node, *fragnode = NULL;
+ bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id);
+ struct listnode *fragnode = NULL;
uint32_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;
- struct ipv6_reachability *ip6reach;
static const u_char null_sysid[ISIS_SYS_ID_LEN];
- struct mt_router_info *mt_router_info = NULL;
+ struct isis_mt_router_info *mt_router_info = NULL;
+
+ if (!lsp->tlvs)
+ return ISIS_OK;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST)
- mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data,
- spftree->mtid);
+ mt_router_info = isis_tlvs_lookup_mt_router_info(lsp->tlvs,
+ spftree->mtid);
if (!pseudo_lsp && (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !speaks(lsp->tlv_data.nlpids, spftree->family))
+ && !speaks(lsp->tlvs->protocols_supported.protocols,
+ lsp->tlvs->protocols_supported.count,
+ spftree->family))
&& !mt_router_info)
return ISIS_OK;
lspfragloop:
- if (lsp->lsp_header->seq_num == 0) {
+ if (lsp->hdr.seqno == 0) {
zlog_warn(
"isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
return ISIS_WARNING;
@@ -663,142 +683,122 @@ lspfragloop:
#ifdef EXTREME_DEBUG
zlog_debug("ISIS-Spf: process_lsp %s",
- print_sys_hostname(lsp->lsp_header->lsp_id));
+ print_sys_hostname(lsp->hdr.lsp_id));
#endif /* EXTREME_DEBUG */
/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
if (pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits))
+ && !ISIS_MASK_LSP_OL_BIT(lsp->hdr.lsp_bits))
|| (mt_router_info && !mt_router_info->overload))
{
if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, node,
- is_neigh)) {
+ struct isis_oldstyle_reach *r;
+ for (r = (struct isis_oldstyle_reach *)
+ lsp->tlvs->oldstyle_reach.head;
+ r; r = r->next) {
/* C.2.6 a) */
/* Two way connectivity */
- if (!memcmp(is_neigh->neigh_id, root_sysid,
- ISIS_SYS_ID_LEN))
+ if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
- && !memcmp(is_neigh->neigh_id, null_sysid,
+ && !memcmp(r->id, null_sysid,
ISIS_SYS_ID_LEN))
continue;
- dist = cost + is_neigh->metrics.metric_default;
+ dist = cost + r->metric;
process_N(spftree,
- LSP_PSEUDO_ID(is_neigh->neigh_id)
+ LSP_PSEUDO_ID(r->id)
? VTYPE_PSEUDO_IS
: VTYPE_NONPSEUDO_IS,
- (void *)is_neigh->neigh_id, dist,
- depth + 1, parent);
+ (void *)r->id, dist, depth + 1,
+ parent);
}
}
- struct list *te_is_neighs = NULL;
- if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- te_is_neighs = lsp->tlv_data.te_is_neighs;
- } else {
- struct tlv_mt_neighbors *mt_neighbors;
- mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data,
- spftree->mtid);
- if (mt_neighbors)
- te_is_neighs = mt_neighbors->list;
- }
- for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) {
- if (!memcmp(te_is_neigh->neigh_id, root_sysid,
- ISIS_SYS_ID_LEN))
+ struct isis_item_list *te_neighs = NULL;
+ if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ te_neighs = &lsp->tlvs->extended_reach;
+ else
+ te_neighs = isis_lookup_mt_items(&lsp->tlvs->mt_reach,
+ spftree->mtid);
+
+ struct isis_extended_reach *er;
+ for (er = te_neighs
+ ? (struct isis_extended_reach *)
+ te_neighs->head
+ : NULL;
+ er; er = er->next) {
+ if (!memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
- && !memcmp(te_is_neigh->neigh_id, null_sysid,
- ISIS_SYS_ID_LEN))
+ && !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
continue;
- dist = cost + GET_TE_METRIC(te_is_neigh);
+ dist = cost + er->metric;
process_N(spftree,
- LSP_PSEUDO_ID(te_is_neigh->neigh_id)
- ? VTYPE_PSEUDO_TE_IS
- : VTYPE_NONPSEUDO_TE_IS,
- (void *)te_is_neigh->neigh_id, dist,
- depth + 1, parent);
+ LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
+ : VTYPE_NONPSEUDO_TE_IS,
+ (void *)er->id, dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET
&& spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs,
- lsp->tlv_data.ipv4_ext_reachs};
+ struct isis_item_list *reachs[] = {
+ &lsp->tlvs->oldstyle_ip_reach,
+ &lsp->tlvs->oldstyle_ip_reach_ext};
- prefix.family = AF_INET;
for (unsigned int i = 0; i < array_size(reachs); i++) {
- vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs)
- ? VTYPE_IPREACH_INTERNAL
- : VTYPE_IPREACH_EXTERNAL;
- for (ALL_LIST_ELEMENTS_RO(reachs[i], node, ipreach)) {
- dist = cost + ipreach->metrics.metric_default;
- prefix.u.prefix4 = ipreach->prefix;
- prefix.prefixlen = ip_masklen(ipreach->mask);
- apply_mask(&prefix);
- process_N(spftree, vtype, (void *)&prefix, dist,
- depth + 1, parent);
+ vtype = i ? VTYPE_IPREACH_EXTERNAL
+ : VTYPE_IPREACH_INTERNAL;
+
+ struct isis_oldstyle_ip_reach *r;
+ for (r = (struct isis_oldstyle_ip_reach *)reachs[i]
+ ->head;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ process_N(spftree, vtype, (void *)&r->prefix,
+ dist, depth + 1, parent);
}
}
}
if (!pseudo_lsp && spftree->family == AF_INET) {
- struct list *ipv4reachs = NULL;
-
- if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- ipv4reachs = lsp->tlv_data.te_ipv4_reachs;
- } else {
- struct tlv_mt_ipv4_reachs *mt_reachs;
- mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data,
- spftree->mtid);
- if (mt_reachs)
- ipv4reachs = mt_reachs->list;
- }
-
- prefix.family = AF_INET;
- for (ALL_LIST_ELEMENTS_RO(ipv4reachs, node, te_ipv4_reach)) {
- assert((te_ipv4_reach->control & 0x3F)
- <= IPV4_MAX_BITLEN);
-
- dist = cost + ntohl(te_ipv4_reach->te_metric);
- prefix.u.prefix4 =
- newprefix2inaddr(&te_ipv4_reach->prefix_start,
- te_ipv4_reach->control);
- prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
- apply_mask(&prefix);
- process_N(spftree, VTYPE_IPREACH_TE, (void *)&prefix,
+ struct isis_item_list *ipv4_reachs;
+ if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ ipv4_reachs = &lsp->tlvs->extended_ip_reach;
+ else
+ ipv4_reachs = isis_lookup_mt_items(
+ &lsp->tlvs->mt_ip_reach, spftree->mtid);
+
+ struct isis_extended_ip_reach *r;
+ for (r = ipv4_reachs
+ ? (struct isis_extended_ip_reach *)
+ ipv4_reachs->head
+ : NULL;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ process_N(spftree, VTYPE_IPREACH_TE, (void *)&r->prefix,
dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET6) {
- struct list *ipv6reachs = NULL;
-
- if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
- ipv6reachs = lsp->tlv_data.ipv6_reachs;
- } else {
- struct tlv_mt_ipv6_reachs *mt_reachs;
- mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data,
- spftree->mtid);
- if (mt_reachs)
- ipv6reachs = mt_reachs->list;
- }
-
- prefix.family = AF_INET6;
- for (ALL_LIST_ELEMENTS_RO(ipv6reachs, node, ip6reach)) {
- assert(ip6reach->prefix_len <= IPV6_MAX_BITLEN);
-
- dist = cost + ntohl(ip6reach->metric);
- vtype = (ip6reach->control_info
- & CTRL_INFO_DISTRIBUTION)
- ? VTYPE_IP6REACH_EXTERNAL
- : VTYPE_IP6REACH_INTERNAL;
- prefix.prefixlen = ip6reach->prefix_len;
- memcpy(&prefix.u.prefix6.s6_addr, ip6reach->prefix,
- PSIZE(ip6reach->prefix_len));
- apply_mask(&prefix);
- process_N(spftree, vtype, (void *)&prefix, dist,
+ struct isis_item_list *ipv6_reachs;
+ if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+ ipv6_reachs = &lsp->tlvs->ipv6_reach;
+ else
+ ipv6_reachs = isis_lookup_mt_items(
+ &lsp->tlvs->mt_ipv6_reach, spftree->mtid);
+
+ struct isis_ipv6_reach *r;
+ for (r = ipv6_reachs
+ ? (struct isis_ipv6_reach *)ipv6_reachs->head
+ : NULL;
+ r; r = r->next) {
+ dist = cost + r->metric;
+ vtype = r->external ? VTYPE_IP6REACH_EXTERNAL
+ : VTYPE_IP6REACH_INTERNAL;
+ process_N(spftree, vtype, (void *)&r->prefix, dist,
depth + 1, parent);
}
}
@@ -893,7 +893,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
if (!adj_has_mt(adj, spftree->mtid))
continue;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST
- && !speaks(&adj->nlpids, spftree->family))
+ && !speaks(adj->nlpids.nlpids,
+ adj->nlpids.count,
+ spftree->family))
continue;
switch (adj->sys_type) {
case ISIS_SYSTYPE_ES:
@@ -928,8 +930,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
->lspdb[spftree->level
- 1]);
if (lsp == NULL
- || lsp->lsp_header->rem_lifetime
- == 0)
+ || lsp->hdr.rem_lifetime == 0)
zlog_warn(
"ISIS-Spf: No LSP %s found for IS adjacency "
"L%d on %s (ID %u)",
@@ -979,7 +980,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
lsp = lsp_search(
lsp_id,
spftree->area->lspdb[spftree->level - 1]);
- if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) {
+ if (lsp == NULL || lsp->hdr.rem_lifetime == 0) {
zlog_warn(
"ISIS-Spf: No lsp (%p) found from root "
"to L%d DR %s on %s (ID %d)",
@@ -1015,7 +1016,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
LSP_PSEUDO_ID(lsp_id) = 0;
LSP_FRAGMENT(lsp_id) = 0;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST
- || speaks(&adj->nlpids, spftree->family))
+ || speaks(adj->nlpids.nlpids,
+ adj->nlpids.count,
+ spftree->family))
isis_spf_add_local(
spftree,
spftree->area->oldmetric
@@ -1178,7 +1181,7 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
LSP_FRAGMENT(lsp_id) = 0;
lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
- if (lsp && lsp->lsp_header->rem_lifetime != 0) {
+ if (lsp && lsp->hdr.rem_lifetime != 0) {
isis_spf_process_lsp(spftree, lsp, vertex->d_N,
vertex->depth, sysid,
vertex);