summaryrefslogtreecommitdiff
path: root/isisd
diff options
context:
space:
mode:
Diffstat (limited to 'isisd')
-rw-r--r--isisd/ChangeLog6
-rw-r--r--isisd/isis_spf.c127
-rw-r--r--isisd/isis_spf.h5
3 files changed, 107 insertions, 31 deletions
diff --git a/isisd/ChangeLog b/isisd/ChangeLog
index e3fe6257..7f3cd9da 100644
--- a/isisd/ChangeLog
+++ b/isisd/ChangeLog
@@ -1,5 +1,11 @@
2005-09-26 Hasso Tepper <hasso at quagga.net>
+ * isis_spf.[ch]: Added TE TLVs to the SPF process. It seems to work
+ mostly, but needs certainly much more testing, especially transition
+ situation.
+
+2005-09-26 Hasso Tepper <hasso at quagga.net>
+
* isis_lsp.c: Put correct metric info into TE TLV's. Wide metric is
used only if only wide metric style (extended TLV's) is in use.
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 1a5a2db0..ac4c71f3 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -124,9 +124,15 @@ vtype2string (enum vertextype vtype)
case VTYPE_PSEUDO_IS:
return "pseudo_IS";
break;
+ case VTYPE_PSEUDO_TE_IS:
+ return "pseudo_TE-IS";
+ break;
case VTYPE_NONPSEUDO_IS:
return "IS";
break;
+ case VTYPE_NONPSEUDO_TE_IS:
+ return "TE-IS";
+ break;
case VTYPE_ES:
return "ES";
break;
@@ -136,6 +142,9 @@ vtype2string (enum vertextype vtype)
case VTYPE_IPREACH_EXTERNAL:
return "IP external";
break;
+ case VTYPE_IPREACH_TE:
+ return "IP TE";
+ break;
#ifdef HAVE_IPV6
case VTYPE_IP6REACH_INTERNAL:
return "IP6 internal";
@@ -156,14 +165,17 @@ vid2string (struct isis_vertex *vertex, u_char * buff)
switch (vertex->type)
{
case VTYPE_PSEUDO_IS:
+ case VTYPE_PSEUDO_TE_IS:
return rawlspid_print (vertex->N.id);
break;
case VTYPE_NONPSEUDO_IS:
+ case VTYPE_NONPSEUDO_TE_IS:
case VTYPE_ES:
return sysid_print (vertex->N.id);
break;
case VTYPE_IPREACH_INTERNAL:
case VTYPE_IPREACH_EXTERNAL:
+ case VTYPE_IPREACH_TE:
#ifdef HAVE_IPV6
case VTYPE_IP6REACH_INTERNAL:
case VTYPE_IP6REACH_EXTERNAL:
@@ -267,13 +279,16 @@ isis_vertex_new (void *id, enum vertextype vtype)
{
case VTYPE_ES:
case VTYPE_NONPSEUDO_IS:
+ case VTYPE_NONPSEUDO_TE_IS:
memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN);
break;
case VTYPE_PSEUDO_IS:
+ case VTYPE_PSEUDO_TE_IS:
memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
break;
case VTYPE_IPREACH_INTERNAL:
case VTYPE_IPREACH_EXTERNAL:
+ case VTYPE_IPREACH_TE:
#ifdef HAVE_IPV6
case VTYPE_IP6REACH_INTERNAL:
case VTYPE_IP6REACH_EXTERNAL:
@@ -312,7 +327,11 @@ isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
if (lsp == NULL)
zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
- vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
+ 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);
@@ -341,15 +360,18 @@ isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
{
case VTYPE_ES:
case VTYPE_NONPSEUDO_IS:
+ case VTYPE_NONPSEUDO_TE_IS:
if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
return vertex;
break;
case VTYPE_PSEUDO_IS:
+ case VTYPE_PSEUDO_TE_IS:
if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
return vertex;
break;
case VTYPE_IPREACH_INTERNAL:
case VTYPE_IPREACH_EXTERNAL:
+ case VTYPE_IPREACH_TE:
#ifdef HAVE_IPV6
case VTYPE_IP6REACH_INTERNAL:
case VTYPE_IP6REACH_EXTERNAL:
@@ -536,7 +558,9 @@ isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
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
@@ -574,6 +598,22 @@ lspfragloop:
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;
@@ -603,6 +643,21 @@ lspfragloop:
lsp->adj, family);
}
}
+ if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs)
+ {
+ prefix.family = AF_INET;
+ for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
+ node, te_ipv4_reach))
+ {
+ dist = cost + ntohl (te_ipv4_reach->te_metric);
+ vtype = VTYPE_IPREACH_TE;
+ prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start,
+ te_ipv4_reach->control);
+ prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
+ process_N (spftree, vtype, (void *) &prefix, dist, depth + 1,
+ lsp->adj, family);
+ }
+ }
#ifdef HAVE_IPV6
if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs)
{
@@ -644,6 +699,7 @@ isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,
{
struct listnode *node, *nnode, *fragnode = NULL;
struct is_neigh *is_neigh;
+ struct te_is_neigh *te_is_neigh;
enum vertextype vtype;
pseudofragloop:
@@ -655,23 +711,42 @@ pseudofragloop:
return ISIS_WARNING;
}
- for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, node, nnode, is_neigh))
- {
- vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
- : VTYPE_NONPSEUDO_IS;
- /* Two way connectivity */
- if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
- continue;
- if (isis_find_vertex
- (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
- && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
+ if (lsp->tlv_data.is_neighs)
+ for (ALL_LIST_ELEMENTS (lsp->tlv_data.is_neighs, node, nnode, is_neigh))
+ {
+ vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
+ : VTYPE_NONPSEUDO_IS;
+ /* Two way connectivity */
+ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
+ continue;
+ if (isis_find_vertex
+ (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL
+ && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id,
vtype) == NULL)
- {
- /* C.2.5 i) */
- isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
+ {
+ /* C.2.5 i) */
+ isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj,
cost, depth, family);
- }
- }
+ }
+ }
+ if (lsp->tlv_data.te_is_neighs)
+ for (ALL_LIST_ELEMENTS (lsp->tlv_data.te_is_neighs, node, nnode, te_is_neigh))
+ {
+ vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS
+ : VTYPE_NONPSEUDO_TE_IS;
+ /* Two way connectivity */
+ if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
+ continue;
+ if (isis_find_vertex
+ (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL
+ && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id,
+ vtype) == NULL)
+ {
+ /* C.2.5 i) */
+ isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj,
+ cost, depth, family);
+ }
+ }
if (fragnode == NULL)
fragnode = listhead (lsp->lspu.frags);
@@ -777,9 +852,7 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
{
case ISIS_SYSTYPE_ES:
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
- circuit->metrics[level -
- 1].metric_default,
- family);
+ circuit->te_metric[level - 1], family);
break;
case ISIS_SYSTYPE_IS:
case ISIS_SYSTYPE_L1_IS:
@@ -787,9 +860,7 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
vertex =
isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS,
adj->sysid, adj,
- circuit->metrics[level -
- 1].metric_default,
- family);
+ circuit->te_metric[level - 1], family);
memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
LSP_PSEUDO_ID (lsp_id) = 0;
LSP_FRAGMENT (lsp_id) = 0;
@@ -827,9 +898,8 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
}
else
{
- isis_spf_process_pseudo_lsp
- (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
- family);
+ isis_spf_process_pseudo_lsp (spftree, lsp,
+ circuit->te_metric[level - 1], 0, family);
}
}
@@ -842,17 +912,14 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
{
case ISIS_SYSTYPE_ES:
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
- circuit->metrics[level - 1].metric_default,
- family);
+ circuit->te_metric[level - 1], family);
break;
case ISIS_SYSTYPE_IS:
case ISIS_SYSTYPE_L1_IS:
case ISIS_SYSTYPE_L2_IS:
if (speaks (&adj->nlpids, family))
isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid,
- adj,
- circuit->metrics[level -
- 1].metric_default,
+ adj, circuit->te_metric[level - 1],
family);
break;
case ISIS_SYSTYPE_UNKNOWN:
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
index 8912add3..6bdab2da 100644
--- a/isisd/isis_spf.h
+++ b/isisd/isis_spf.h
@@ -27,10 +27,13 @@
enum vertextype
{
VTYPE_PSEUDO_IS = 1,
+ VTYPE_PSEUDO_TE_IS,
VTYPE_NONPSEUDO_IS,
+ VTYPE_NONPSEUDO_TE_IS,
VTYPE_ES,
VTYPE_IPREACH_INTERNAL,
- VTYPE_IPREACH_EXTERNAL
+ VTYPE_IPREACH_EXTERNAL,
+ VTYPE_IPREACH_TE
#ifdef HAVE_IPV6
,
VTYPE_IP6REACH_INTERNAL,