2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* IS-IS Rout(e)ing protocol - isis_spf.c
|
|
|
|
* The SPT algorithm
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
|
|
* Tampere University of Technology
|
|
|
|
* Institute of Communications Engineering
|
2017-04-27 12:54:21 +02:00
|
|
|
* Copyright (C) 2017 Christian Franke <chris@opensourcerouting.org>
|
2003-12-23 09:09:43 +01:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public Licenseas published by the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "vty.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "table.h"
|
2017-02-21 23:52:29 +01:00
|
|
|
#include "spf_backoff.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
#include "isis_constants.h"
|
|
|
|
#include "isis_common.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isis_flags.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "dict.h"
|
|
|
|
#include "isisd.h"
|
|
|
|
#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"
|
|
|
|
#include "isis_spf.h"
|
|
|
|
#include "isis_route.h"
|
|
|
|
#include "isis_csm.h"
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
|
|
|
|
|
|
|
|
struct isis_spf_run {
|
|
|
|
struct isis_area *area;
|
|
|
|
int level;
|
|
|
|
};
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* 7.2.7 */
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
remove_excess_adjs (struct list *adjs)
|
|
|
|
{
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *node, *excess = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_adjacency *adj, *candidate = NULL;
|
|
|
|
int comp;
|
|
|
|
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (adjs, node, adj))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (excess == NULL)
|
|
|
|
excess = node;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
candidate = listgetdata (excess);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (candidate->sys_type < adj->sys_type)
|
|
|
|
{
|
|
|
|
excess = node;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (candidate->sys_type > adj->sys_type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
if (comp > 0)
|
|
|
|
{
|
|
|
|
excess = node;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (comp < 0)
|
|
|
|
continue;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
|
|
|
|
{
|
|
|
|
excess = node;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
|
|
|
|
if (comp > 0)
|
|
|
|
{
|
|
|
|
excess = node;
|
|
|
|
continue;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete_node (adjs, excess);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static const char *
|
2003-12-23 09:09:43 +01:00
|
|
|
vtype2string (enum vertextype vtype)
|
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
switch (vtype)
|
|
|
|
{
|
|
|
|
case VTYPE_PSEUDO_IS:
|
|
|
|
return "pseudo_IS";
|
|
|
|
break;
|
2005-09-26 20:15:36 +02:00
|
|
|
case VTYPE_PSEUDO_TE_IS:
|
|
|
|
return "pseudo_TE-IS";
|
|
|
|
break;
|
2004-09-10 22:48:21 +02:00
|
|
|
case VTYPE_NONPSEUDO_IS:
|
|
|
|
return "IS";
|
|
|
|
break;
|
2005-09-26 20:15:36 +02:00
|
|
|
case VTYPE_NONPSEUDO_TE_IS:
|
|
|
|
return "TE-IS";
|
|
|
|
break;
|
2004-09-10 22:48:21 +02:00
|
|
|
case VTYPE_ES:
|
|
|
|
return "ES";
|
|
|
|
break;
|
|
|
|
case VTYPE_IPREACH_INTERNAL:
|
|
|
|
return "IP internal";
|
|
|
|
break;
|
|
|
|
case VTYPE_IPREACH_EXTERNAL:
|
|
|
|
return "IP external";
|
|
|
|
break;
|
2005-09-26 20:15:36 +02:00
|
|
|
case VTYPE_IPREACH_TE:
|
|
|
|
return "IP TE";
|
|
|
|
break;
|
2004-09-10 22:48:21 +02:00
|
|
|
case VTYPE_IP6REACH_INTERNAL:
|
|
|
|
return "IP6 internal";
|
|
|
|
break;
|
|
|
|
case VTYPE_IP6REACH_EXTERNAL:
|
|
|
|
return "IP6 external";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return "UNKNOWN";
|
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
return NULL; /* Not reached */
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static const char *
|
2015-11-23 21:44:34 +01:00
|
|
|
vid2string (struct isis_vertex *vertex, char * buff, int size)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
return print_sys_hostname (vertex->N.id);
|
2017-04-27 12:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VTYPE_IP(vertex->type))
|
|
|
|
{
|
2015-11-23 21:44:34 +01:00
|
|
|
prefix2str ((struct prefix *) &vertex->N.prefix, buff, size);
|
2017-04-27 12:54:21 +02:00
|
|
|
return buff;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
return "UNKNOWN";
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
static struct isis_vertex *
|
|
|
|
isis_vertex_new (void *id, enum vertextype vtype)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_vertex *vertex;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
vertex->type = vtype;
|
2017-04-27 12:54:21 +02:00
|
|
|
|
|
|
|
if (VTYPE_IS(vtype) || VTYPE_ES(vtype))
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
|
|
|
memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1);
|
2017-04-27 12:54:21 +02:00
|
|
|
}
|
|
|
|
else if (VTYPE_IP(vtype))
|
|
|
|
{
|
|
|
|
memcpy (&vertex->N.prefix, (struct prefix *) id, sizeof (struct prefix));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_err ("WTF!");
|
|
|
|
}
|
|
|
|
|
|
|
|
vertex->Adj_N = list_new ();
|
|
|
|
vertex->parents = list_new ();
|
|
|
|
vertex->children = list_new ();
|
|
|
|
|
|
|
|
return vertex;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2003-12-23 09:09:43 +01:00
|
|
|
isis_vertex_del (struct isis_vertex *vertex)
|
|
|
|
{
|
|
|
|
list_delete (vertex->Adj_N);
|
2012-03-24 16:35:20 +01:00
|
|
|
vertex->Adj_N = NULL;
|
|
|
|
list_delete (vertex->parents);
|
|
|
|
vertex->parents = NULL;
|
|
|
|
list_delete (vertex->children);
|
|
|
|
vertex->children = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
memset(vertex, 0, sizeof(struct isis_vertex));
|
2003-12-23 09:09:43 +01:00
|
|
|
XFREE (MTYPE_ISIS_VERTEX, vertex);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_vertex_adj_del (struct isis_vertex *vertex, struct isis_adjacency *adj)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nextnode;
|
|
|
|
if (!vertex)
|
|
|
|
return;
|
|
|
|
for (node = listhead (vertex->Adj_N); node; node = nextnode)
|
|
|
|
{
|
|
|
|
nextnode = listnextnode(node);
|
|
|
|
if (listgetdata(node) == adj)
|
|
|
|
list_delete_node(vertex->Adj_N, node);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct isis_spftree *
|
|
|
|
isis_spftree_new (struct isis_area *area)
|
|
|
|
{
|
|
|
|
struct isis_spftree *tree;
|
|
|
|
|
|
|
|
tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
|
|
|
|
if (tree == NULL)
|
|
|
|
{
|
|
|
|
zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tree->tents = list_new ();
|
|
|
|
tree->paths = list_new ();
|
|
|
|
tree->area = area;
|
2012-03-28 08:48:05 +02:00
|
|
|
tree->last_run_timestamp = 0;
|
|
|
|
tree->last_run_duration = 0;
|
2012-03-24 16:35:20 +01:00
|
|
|
tree->runcount = 0;
|
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-12-23 09:09:43 +01:00
|
|
|
isis_spftree_del (struct isis_spftree *spftree)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2004-09-26 18:24:14 +02:00
|
|
|
spftree->tents->del = (void (*)(void *)) isis_vertex_del;
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete (spftree->tents);
|
2012-03-24 16:35:20 +01:00
|
|
|
spftree->tents = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2004-09-26 18:24:14 +02:00
|
|
|
spftree->paths->del = (void (*)(void *)) isis_vertex_del;
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete (spftree->paths);
|
2012-03-24 16:35:20 +01:00
|
|
|
spftree->paths = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
XFREE (MTYPE_ISIS_SPFTREE, spftree);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
static void
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_spftree_adj_del (struct isis_spftree *spftree, struct isis_adjacency *adj)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
if (!adj)
|
|
|
|
return;
|
|
|
|
for (node = listhead (spftree->tents); node; node = listnextnode (node))
|
|
|
|
isis_vertex_adj_del (listgetdata (node), adj);
|
|
|
|
for (node = listhead (spftree->paths); node; node = listnextnode (node))
|
|
|
|
isis_vertex_adj_del (listgetdata (node), adj);
|
|
|
|
return;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
void
|
2003-12-23 09:09:43 +01:00
|
|
|
spftree_area_init (struct isis_area *area)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
if (area->is_type & IS_LEVEL_1)
|
|
|
|
{
|
|
|
|
if (area->spftree[0] == NULL)
|
|
|
|
area->spftree[0] = isis_spftree_new (area);
|
|
|
|
if (area->spftree6[0] == NULL)
|
|
|
|
area->spftree6[0] = isis_spftree_new (area);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (area->is_type & IS_LEVEL_2)
|
|
|
|
{
|
|
|
|
if (area->spftree[1] == NULL)
|
|
|
|
area->spftree[1] = isis_spftree_new (area);
|
|
|
|
if (area->spftree6[1] == NULL)
|
|
|
|
area->spftree6[1] = isis_spftree_new (area);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
void
|
|
|
|
spftree_area_del (struct isis_area *area)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
if (area->is_type & IS_LEVEL_1)
|
|
|
|
{
|
|
|
|
if (area->spftree[0] != NULL)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_spftree_del (area->spftree[0]);
|
|
|
|
area->spftree[0] = NULL;
|
|
|
|
}
|
|
|
|
if (area->spftree6[0])
|
|
|
|
{
|
|
|
|
isis_spftree_del (area->spftree6[0]);
|
|
|
|
area->spftree6[0] = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (area->is_type & IS_LEVEL_2)
|
|
|
|
{
|
|
|
|
if (area->spftree[1] != NULL)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_spftree_del (area->spftree[1]);
|
|
|
|
area->spftree[1] = NULL;
|
|
|
|
}
|
2012-11-27 02:10:27 +01:00
|
|
|
if (area->spftree6[1] != NULL)
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
|
|
|
isis_spftree_del (area->spftree6[1]);
|
|
|
|
area->spftree6[1] = NULL;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
return;
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
void
|
|
|
|
spftree_area_adj_del (struct isis_area *area, struct isis_adjacency *adj)
|
|
|
|
{
|
|
|
|
if (area->is_type & IS_LEVEL_1)
|
|
|
|
{
|
|
|
|
if (area->spftree[0] != NULL)
|
|
|
|
isis_spftree_adj_del (area->spftree[0], adj);
|
|
|
|
if (area->spftree6[0] != NULL)
|
|
|
|
isis_spftree_adj_del (area->spftree6[0], adj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (area->is_type & IS_LEVEL_2)
|
|
|
|
{
|
|
|
|
if (area->spftree[1] != NULL)
|
|
|
|
isis_spftree_adj_del (area->spftree[1], adj);
|
|
|
|
if (area->spftree6[1] != NULL)
|
|
|
|
isis_spftree_adj_del (area->spftree6[1], adj);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2012-03-28 08:48:05 +02:00
|
|
|
struct isis_lsp *lsp;
|
2012-03-24 16:35:20 +01:00
|
|
|
u_char lspid[ISIS_SYS_ID_LEN + 2];
|
|
|
|
|
|
|
|
memcpy (lspid, sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID (lspid) = 0;
|
|
|
|
LSP_FRAGMENT (lspid) = 0;
|
2012-03-28 08:48:05 +02:00
|
|
|
lsp = lsp_search (lspid, area->lspdb[level - 1]);
|
|
|
|
if (lsp && lsp->lsp_header->rem_lifetime != 0)
|
|
|
|
return lsp;
|
|
|
|
return NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add this IS to the root of SPT
|
|
|
|
*/
|
2012-03-24 16:35:20 +01:00
|
|
|
static struct isis_vertex *
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_add_root (struct isis_spftree *spftree, u_char *sysid)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_vertex *vertex;
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
#ifdef EXTREME_DEBUG
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2017-04-27 12:54:21 +02:00
|
|
|
u_char id[ISIS_SYS_ID_LEN + 1];
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
memcpy(id, sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID(id) = 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
lsp = isis_root_system_lsp (spftree->area, spftree->level, sysid);
|
|
|
|
if (lsp == NULL)
|
|
|
|
zlog_warn ("ISIS-Spf: could not find own l%d LSP!", spftree->level);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
vertex = isis_vertex_new (id, spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS
|
|
|
|
: VTYPE_NONPSEUDO_TE_IS);
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (spftree->paths, vertex);
|
|
|
|
|
|
|
|
#ifdef EXTREME_DEBUG
|
2004-12-24 01:14:50 +01:00
|
|
|
zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS",
|
2015-11-23 21:44:34 +01:00
|
|
|
vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)),
|
2004-12-24 01:14:50 +01:00
|
|
|
vertex->depth, vertex->d_N);
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
return vertex;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static struct isis_vertex *
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct isis_vertex *vertex;
|
|
|
|
struct prefix *p1, *p2;
|
|
|
|
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (list, node, vertex))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (vertex->type != vtype)
|
2017-04-27 12:54:21 +02:00
|
|
|
continue;
|
|
|
|
if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type))
|
|
|
|
{
|
|
|
|
if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
|
|
|
|
return vertex;
|
|
|
|
}
|
|
|
|
if (VTYPE_IP(vertex->type))
|
|
|
|
{
|
|
|
|
p1 = (struct prefix *) id;
|
|
|
|
p2 = (struct prefix *) &vertex->N.id;
|
|
|
|
if (p1->family == p2->family
|
|
|
|
&& p1->prefixlen == p2->prefixlen
|
|
|
|
&& !memcmp(&p1->u.prefix, &p2->u.prefix, PSIZE (p1->prefixlen)))
|
|
|
|
{
|
|
|
|
return vertex;
|
|
|
|
}
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
/*
|
|
|
|
* Compares vertizes for sorting in the TENT list. Returns true
|
|
|
|
* if candidate should be considered before current, false otherwise.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
tent_cmp (struct isis_vertex *current, struct isis_vertex *candidate)
|
|
|
|
{
|
|
|
|
if (current->d_N > candidate->d_N)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (current->d_N == candidate->d_N
|
|
|
|
&& current->type > candidate->type)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* Add a vertex to TENT sorted by cost and by vertextype on tie break situation
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static struct isis_vertex *
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
|
2017-04-27 12:54:21 +02:00
|
|
|
void *id, uint32_t cost, int depth,
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_adjacency *adj, struct isis_vertex *parent)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_vertex *vertex, *v;
|
|
|
|
struct listnode *node;
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_adjacency *parent_adj;
|
2004-09-10 22:48:21 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
assert (isis_find_vertex (spftree->paths, id, vtype) == NULL);
|
|
|
|
assert (isis_find_vertex (spftree->tents, id, vtype) == NULL);
|
2003-12-23 09:09:43 +01:00
|
|
|
vertex = isis_vertex_new (id, vtype);
|
|
|
|
vertex->d_N = cost;
|
|
|
|
vertex->depth = depth;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (parent) {
|
|
|
|
listnode_add (vertex->parents, parent);
|
|
|
|
if (listnode_lookup (parent->children, vertex) == NULL)
|
|
|
|
listnode_add (parent->children, vertex);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
|
|
|
|
listnode_add (vertex->Adj_N, parent_adj);
|
|
|
|
} else if (adj) {
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (vertex->Adj_N, adj);
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug ("ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d",
|
|
|
|
print_sys_hostname (vertex->N.id),
|
2015-11-23 21:44:34 +01:00
|
|
|
vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)),
|
2012-03-24 16:35:20 +01:00
|
|
|
vertex->depth, vertex->d_N, listcount(vertex->Adj_N));
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (list_isempty (spftree->tents))
|
|
|
|
{
|
|
|
|
listnode_add (spftree->tents, vertex);
|
|
|
|
return vertex;
|
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
|
|
|
|
/* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (node = listhead (spftree->tents); node; node = listnextnode (node))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
v = listgetdata (node);
|
2017-04-27 12:54:21 +02:00
|
|
|
if (tent_cmp(v, vertex))
|
|
|
|
{
|
2016-07-28 17:23:46 +02:00
|
|
|
listnode_add_before (spftree->tents, node, vertex);
|
2017-04-27 12:54:21 +02:00
|
|
|
break;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
|
|
|
|
if (node == NULL)
|
|
|
|
listnode_add (spftree->tents, vertex);
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return vertex;
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
|
2012-03-24 16:35:20 +01:00
|
|
|
void *id, struct isis_adjacency *adj, uint32_t cost,
|
2017-04-27 12:54:21 +02:00
|
|
|
struct isis_vertex *parent)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_vertex *vertex;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
|
|
|
vertex = isis_find_vertex (spftree->tents, id, vtype);
|
|
|
|
|
|
|
|
if (vertex)
|
|
|
|
{
|
|
|
|
/* C.2.5 c) */
|
|
|
|
if (vertex->d_N == cost)
|
|
|
|
{
|
|
|
|
if (adj)
|
|
|
|
listnode_add (vertex->Adj_N, adj);
|
|
|
|
/* d) */
|
|
|
|
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
|
|
|
|
remove_excess_adjs (vertex->Adj_N);
|
2012-03-24 16:35:20 +01:00
|
|
|
if (parent && (listnode_lookup (vertex->parents, parent) == NULL))
|
|
|
|
listnode_add (vertex->parents, parent);
|
|
|
|
if (parent && (listnode_lookup (parent->children, vertex) == NULL))
|
|
|
|
listnode_add (parent->children, vertex);
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
else if (vertex->d_N < cost)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
/* e) do nothing */
|
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
else { /* vertex->d_N > cost */
|
|
|
|
/* f) */
|
|
|
|
struct listnode *pnode, *pnextnode;
|
|
|
|
struct isis_vertex *pvertex;
|
|
|
|
listnode_delete (spftree->tents, vertex);
|
|
|
|
assert (listcount (vertex->children) == 0);
|
|
|
|
for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
|
|
|
|
listnode_delete(pvertex->children, vertex);
|
|
|
|
isis_vertex_del (vertex);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_add2tent (spftree, vtype, id, cost, 1, adj, parent);
|
2012-03-24 16:35:20 +01:00
|
|
|
return;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2004-09-10 22:48:21 +02:00
|
|
|
process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
|
2017-04-27 12:54:21 +02:00
|
|
|
uint32_t dist, uint16_t depth,
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_vertex *parent)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_vertex *vertex;
|
|
|
|
#ifdef EXTREME_DEBUG
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
assert (spftree && parent);
|
|
|
|
|
|
|
|
/* RFC3787 section 5.1 */
|
|
|
|
if (spftree->area->newmetric == 1)
|
|
|
|
{
|
|
|
|
if (dist > MAX_WIDE_PATH_METRIC)
|
|
|
|
return;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
/* C.2.6 b) */
|
2012-03-24 16:35:20 +01:00
|
|
|
else if (spftree->area->oldmetric == 1)
|
|
|
|
{
|
|
|
|
if (dist > MAX_NARROW_PATH_METRIC)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/* c) */
|
|
|
|
vertex = isis_find_vertex (spftree->paths, id, vtype);
|
2004-09-10 22:48:21 +02:00
|
|
|
if (vertex)
|
|
|
|
{
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef EXTREME_DEBUG
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d already found from PATH",
|
|
|
|
print_sys_hostname (vertex->N.id),
|
2015-11-23 21:44:34 +01:00
|
|
|
vtype2string (vtype), vid2string (vertex, buff, sizeof (buff)), dist);
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2004-09-10 22:48:21 +02:00
|
|
|
assert (dist >= vertex->d_N);
|
|
|
|
return;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
vertex = isis_find_vertex (spftree->tents, id, vtype);
|
2004-09-10 22:48:21 +02:00
|
|
|
/* d) */
|
|
|
|
if (vertex)
|
|
|
|
{
|
|
|
|
/* 1) */
|
2003-12-23 09:09:43 +01:00
|
|
|
#ifdef EXTREME_DEBUG
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d",
|
|
|
|
print_sys_hostname (vertex->N.id),
|
2015-11-23 21:44:34 +01:00
|
|
|
vtype2string (vtype), vid2string (vertex, buff, sizeof (buff)), dist,
|
2012-03-24 16:35:20 +01:00
|
|
|
(parent ? print_sys_hostname (parent->N.id) : "null"),
|
|
|
|
(parent ? listcount (parent->Adj_N) : 0));
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2004-09-10 22:48:21 +02:00
|
|
|
if (vertex->d_N == dist)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
struct listnode *node;
|
|
|
|
struct isis_adjacency *parent_adj;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj))
|
|
|
|
if (listnode_lookup(vertex->Adj_N, parent_adj) == NULL)
|
|
|
|
listnode_add (vertex->Adj_N, parent_adj);
|
2004-09-10 22:48:21 +02:00
|
|
|
/* 2) */
|
|
|
|
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
|
|
|
|
remove_excess_adjs (vertex->Adj_N);
|
2012-03-24 16:35:20 +01:00
|
|
|
if (listnode_lookup (vertex->parents, parent) == NULL)
|
|
|
|
listnode_add (vertex->parents, parent);
|
|
|
|
if (listnode_lookup (parent->children, vertex) == NULL)
|
|
|
|
listnode_add (parent->children, vertex);
|
2004-09-10 22:48:21 +02:00
|
|
|
/* 3) */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (vertex->d_N < dist)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
/* 4) */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
struct listnode *pnode, *pnextnode;
|
|
|
|
struct isis_vertex *pvertex;
|
2004-09-10 22:48:21 +02:00
|
|
|
listnode_delete (spftree->tents, vertex);
|
2012-03-24 16:35:20 +01:00
|
|
|
assert (listcount (vertex->children) == 0);
|
|
|
|
for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex))
|
|
|
|
listnode_delete(pvertex->children, vertex);
|
|
|
|
isis_vertex_del (vertex);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
#ifdef EXTREME_DEBUG
|
|
|
|
zlog_debug ("ISIS-Spf: process_N add2tent %s %s dist %d parent %s",
|
|
|
|
print_sys_hostname(id), vtype2string (vtype), dist,
|
|
|
|
(parent ? print_sys_hostname (parent->N.id) : "null"));
|
|
|
|
#endif /* EXTREME_DEBUG */
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_add2tent (spftree, vtype, id, dist, depth, NULL, parent);
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* C.2.6 Step 1
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
|
2017-04-27 12:54:21 +02:00
|
|
|
uint32_t cost, uint16_t depth,
|
2012-03-24 16:35:20 +01:00
|
|
|
u_char *root_sysid, struct isis_vertex *parent)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id);
|
2003-12-23 09:09:43 +01:00
|
|
|
struct listnode *node, *fragnode = NULL;
|
2012-03-24 16:35:20 +01:00
|
|
|
uint32_t dist;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct is_neigh *is_neigh;
|
2005-09-26 20:15:36 +02:00
|
|
|
struct te_is_neigh *te_is_neigh;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct ipv4_reachability *ipreach;
|
2005-09-26 20:15:36 +02:00
|
|
|
struct te_ipv4_reachability *te_ipv4_reach;
|
2003-12-23 09:09:43 +01:00
|
|
|
enum vertextype vtype;
|
|
|
|
struct prefix prefix;
|
|
|
|
struct ipv6_reachability *ip6reach;
|
2012-03-24 16:35:20 +01:00
|
|
|
static const u_char null_sysid[ISIS_SYS_ID_LEN];
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!pseudo_lsp && !speaks (lsp->tlv_data.nlpids, spftree->family))
|
2003-12-23 09:09:43 +01:00
|
|
|
return ISIS_OK;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
lspfragloop:
|
|
|
|
if (lsp->lsp_header->seq_num == 0)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
|
2004-09-10 22:48:21 +02:00
|
|
|
return ISIS_WARNING;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
#ifdef EXTREME_DEBUG
|
|
|
|
zlog_debug ("ISIS-Spf: process_lsp %s", print_sys_hostname(lsp->lsp_header->lsp_id));
|
|
|
|
#endif /* EXTREME_DEBUG */
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
|
|
|
|
if (pseudo_lsp || !ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
|
|
|
if (lsp->tlv_data.is_neighs)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
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, root_sysid, ISIS_SYS_ID_LEN))
|
|
|
|
continue;
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!pseudo_lsp && !memcmp (is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
|
2012-03-24 16:35:20 +01:00
|
|
|
continue;
|
|
|
|
dist = cost + is_neigh->metrics.metric_default;
|
2017-04-27 12:54:21 +02:00
|
|
|
process_N (spftree, LSP_PSEUDO_ID(is_neigh->neigh_id) ? VTYPE_PSEUDO_IS
|
|
|
|
: VTYPE_NONPSEUDO_IS,
|
|
|
|
(void *) is_neigh->neigh_id, dist, depth + 1, parent);
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lsp->tlv_data.te_is_neighs)
|
|
|
|
{
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
|
|
|
|
te_is_neigh))
|
|
|
|
{
|
|
|
|
if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
|
|
|
|
continue;
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!pseudo_lsp && !memcmp (te_is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN))
|
2012-03-24 16:35:20 +01:00
|
|
|
continue;
|
|
|
|
dist = cost + GET_TE_METRIC(te_is_neigh);
|
2017-04-27 12:54:21 +02:00
|
|
|
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);
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!pseudo_lsp && spftree->family == AF_INET)
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs,
|
|
|
|
lsp->tlv_data.ipv4_ext_reachs};
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
prefix.family = AF_INET;
|
2017-04-27 12:54:21 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
|
|
|
|
node, te_ipv4_reach))
|
|
|
|
{
|
2012-05-08 06:27:04 +02:00
|
|
|
assert ((te_ipv4_reach->control & 0x3F) <= IPV4_MAX_BITLEN);
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
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);
|
2017-04-27 12:54:21 +02:00
|
|
|
process_N (spftree, VTYPE_IPREACH_TE, (void *) &prefix, dist, depth + 1,
|
|
|
|
parent);
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
|
|
|
|
if (!pseudo_lsp && spftree->family == AF_INET6)
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
|
|
|
prefix.family = AF_INET6;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach))
|
|
|
|
{
|
2012-05-08 06:27:04 +02:00
|
|
|
assert (ip6reach->prefix_len <= IPV6_MAX_BITLEN);
|
|
|
|
|
2012-11-28 15:39:56 +01:00
|
|
|
dist = cost + ntohl(ip6reach->metric);
|
2012-03-24 16:35:20 +01:00
|
|
|
vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ?
|
2017-04-27 12:54:21 +02:00
|
|
|
VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
|
2012-03-24 16:35:20 +01:00
|
|
|
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, depth + 1,
|
2017-04-27 12:54:21 +02:00
|
|
|
parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (fragnode == NULL)
|
|
|
|
fragnode = listhead (lsp->lspu.frags);
|
2004-09-10 22:48:21 +02:00
|
|
|
else
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
fragnode = listnextnode (fragnode);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
if (fragnode)
|
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
lsp = listgetdata (fragnode);
|
2004-09-10 22:48:21 +02:00
|
|
|
goto lspfragloop;
|
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_preload_tent (struct isis_spftree *spftree,
|
|
|
|
u_char *root_sysid,
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_vertex *parent)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_circuit *circuit;
|
2005-09-28 20:45:54 +02:00
|
|
|
struct listnode *cnode, *anode, *ipnode;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_adjacency *adj;
|
|
|
|
struct isis_lsp *lsp;
|
|
|
|
struct list *adj_list;
|
|
|
|
struct list *adjdb;
|
|
|
|
struct prefix_ipv4 *ipv4;
|
|
|
|
struct prefix prefix;
|
|
|
|
int retval = ISIS_OK;
|
|
|
|
u_char lsp_id[ISIS_SYS_ID_LEN + 2];
|
2012-03-24 16:35:20 +01:00
|
|
|
static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2];
|
2003-12-23 09:09:43 +01:00
|
|
|
struct prefix_ipv6 *ipv6;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (circuit->state != C_STATE_UP)
|
|
|
|
continue;
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!(circuit->is_type & spftree->level))
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
2017-04-27 12:54:21 +02:00
|
|
|
if (spftree->family == AF_INET && !circuit->ip_router)
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
2017-04-27 12:54:21 +02:00
|
|
|
if (spftree->family == AF_INET6 && !circuit->ipv6_router)
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
* Add IP(v6) addresses of this circuit
|
|
|
|
*/
|
2017-04-27 12:54:21 +02:00
|
|
|
if (spftree->family == AF_INET)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
prefix.family = AF_INET;
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
prefix.u.prefix4 = ipv4->prefix;
|
|
|
|
prefix.prefixlen = ipv4->prefixlen;
|
2012-03-24 16:35:20 +01:00
|
|
|
apply_mask (&prefix);
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix,
|
2017-04-27 12:54:21 +02:00
|
|
|
NULL, 0, parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
if (spftree->family == AF_INET6)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
prefix.family = AF_INET6;
|
2005-09-28 20:45:54 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
prefix.prefixlen = ipv6->prefixlen;
|
|
|
|
prefix.u.prefix6 = ipv6->prefix;
|
2012-03-24 16:35:20 +01:00
|
|
|
apply_mask (&prefix);
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL,
|
2017-04-27 12:54:21 +02:00
|
|
|
&prefix, NULL, 0, parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Add the adjacencies
|
|
|
|
*/
|
|
|
|
adj_list = list_new ();
|
2017-04-27 12:54:21 +02:00
|
|
|
adjdb = circuit->u.bc.adjdb[spftree->level - 1];
|
2004-09-10 22:48:21 +02:00
|
|
|
isis_adj_build_up_list (adjdb, adj_list);
|
|
|
|
if (listcount (adj_list) == 0)
|
|
|
|
{
|
|
|
|
list_delete (adj_list);
|
2005-09-04 23:36:36 +02:00
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
|
|
|
zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s",
|
2017-04-27 12:54:21 +02:00
|
|
|
spftree->level, circuit->interface->name);
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!speaks (&adj->nlpids, spftree->family))
|
2004-09-10 22:48:21 +02:00
|
|
|
continue;
|
|
|
|
switch (adj->sys_type)
|
|
|
|
{
|
|
|
|
case ISIS_SYSTYPE_ES:
|
|
|
|
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
|
2017-04-27 12:54:21 +02:00
|
|
|
circuit->te_metric[spftree->level - 1],
|
|
|
|
parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
case ISIS_SYSTYPE_IS:
|
|
|
|
case ISIS_SYSTYPE_L1_IS:
|
|
|
|
case ISIS_SYSTYPE_L2_IS:
|
|
|
|
memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID (lsp_id) = 0;
|
|
|
|
LSP_FRAGMENT (lsp_id) = 0;
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_add_local (spftree,
|
|
|
|
spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS
|
|
|
|
: VTYPE_NONPSEUDO_TE_IS,
|
|
|
|
lsp_id, adj,
|
|
|
|
circuit->te_metric[spftree->level - 1],
|
|
|
|
parent);
|
|
|
|
lsp = lsp_search (lsp_id, spftree->area->lspdb[spftree->level - 1]);
|
2012-03-28 08:48:05 +02:00
|
|
|
if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("ISIS-Spf: No LSP %s found for IS adjacency "
|
|
|
|
"L%d on %s (ID %u)",
|
2017-04-27 12:54:21 +02:00
|
|
|
rawlspid_print (lsp_id), spftree->level,
|
2012-03-24 16:35:20 +01:00
|
|
|
circuit->interface->name, circuit->circuit_id);
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
case ISIS_SYSTYPE_UNKNOWN:
|
|
|
|
default:
|
|
|
|
zlog_warn ("isis_spf_preload_tent unknow adj type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
list_delete (adj_list);
|
|
|
|
/*
|
|
|
|
* Add the pseudonode
|
|
|
|
*/
|
2017-04-27 12:54:21 +02:00
|
|
|
if (spftree->level == 1)
|
2004-09-10 22:48:21 +02:00
|
|
|
memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
|
|
|
|
else
|
|
|
|
memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
|
2012-03-24 16:35:20 +01:00
|
|
|
/* can happen during DR reboot */
|
|
|
|
if (memcmp (lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) == 0)
|
|
|
|
{
|
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
|
|
|
zlog_debug ("ISIS-Spf: No L%d DR on %s (ID %d)",
|
2017-04-27 12:54:21 +02:00
|
|
|
spftree->level, circuit->interface->name, circuit->circuit_id);
|
2012-03-24 16:35:20 +01:00
|
|
|
continue;
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
adj = isis_adj_lookup (lsp_id, adjdb);
|
|
|
|
/* if no adj, we are the dis or error */
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!adj && !circuit->u.bc.is_dr[spftree->level - 1])
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("ISIS-Spf: No adjacency found from root "
|
|
|
|
"to L%d DR %s on %s (ID %d)",
|
2017-04-27 12:54:21 +02:00
|
|
|
spftree->level, rawlspid_print (lsp_id),
|
2012-03-24 16:35:20 +01:00
|
|
|
circuit->interface->name, circuit->circuit_id);
|
|
|
|
continue;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
lsp = lsp_search (lsp_id, spftree->area->lspdb[spftree->level - 1]);
|
2004-09-10 22:48:21 +02:00
|
|
|
if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("ISIS-Spf: No lsp (%p) found from root "
|
|
|
|
"to L%d DR %s on %s (ID %d)",
|
2017-04-27 12:54:21 +02:00
|
|
|
(void *)lsp, spftree->level, rawlspid_print (lsp_id),
|
2015-03-03 08:51:53 +01:00
|
|
|
circuit->interface->name, circuit->circuit_id);
|
2012-03-24 16:35:20 +01:00
|
|
|
continue;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_process_lsp (spftree, lsp,
|
|
|
|
circuit->te_metric[spftree->level - 1], 0,
|
|
|
|
root_sysid, parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
else if (circuit->circ_type == CIRCUIT_T_P2P)
|
|
|
|
{
|
|
|
|
adj = circuit->u.p2p.neighbor;
|
|
|
|
if (!adj)
|
|
|
|
continue;
|
|
|
|
switch (adj->sys_type)
|
|
|
|
{
|
|
|
|
case ISIS_SYSTYPE_ES:
|
|
|
|
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj,
|
2017-04-27 12:54:21 +02:00
|
|
|
circuit->te_metric[spftree->level - 1],
|
2012-03-24 16:35:20 +01:00
|
|
|
parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
case ISIS_SYSTYPE_IS:
|
|
|
|
case ISIS_SYSTYPE_L1_IS:
|
|
|
|
case ISIS_SYSTYPE_L2_IS:
|
2017-04-27 12:54:21 +02:00
|
|
|
memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
|
|
|
|
LSP_PSEUDO_ID (lsp_id) = 0;
|
|
|
|
LSP_FRAGMENT (lsp_id) = 0;
|
|
|
|
if (speaks (&adj->nlpids, spftree->family))
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_spf_add_local (spftree,
|
2017-04-27 12:54:21 +02:00
|
|
|
spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS
|
|
|
|
: VTYPE_NONPSEUDO_TE_IS,
|
|
|
|
lsp_id,
|
|
|
|
adj, circuit->te_metric[spftree->level - 1],
|
|
|
|
parent);
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
case ISIS_SYSTYPE_UNKNOWN:
|
|
|
|
default:
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("isis_spf_preload_tent unknown adj type");
|
2004-09-10 22:48:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
else if (circuit->circ_type == CIRCUIT_T_LOOPBACK)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
else
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
zlog_warn ("isis_spf_preload_tent unsupported media");
|
|
|
|
retval = ISIS_WARNING;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The parent(s) for vertex is set when added to TENT list
|
|
|
|
* now we just put the child pointer(s) in place
|
|
|
|
*/
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2017-04-27 12:54:21 +02:00
|
|
|
add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2012-03-24 16:35:20 +01:00
|
|
|
|
|
|
|
if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
|
|
|
|
return;
|
2003-12-23 09:09:43 +01:00
|
|
|
listnode_add (spftree->paths, vertex);
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug ("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS",
|
|
|
|
print_sys_hostname (vertex->N.id),
|
2015-11-23 21:44:34 +01:00
|
|
|
vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)),
|
2004-12-24 01:14:50 +01:00
|
|
|
vertex->depth, vertex->d_N);
|
2004-09-10 22:48:21 +02:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
if (VTYPE_IP(vertex->type))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (listcount (vertex->Adj_N) > 0)
|
2005-09-26 20:26:26 +02:00
|
|
|
isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
|
2017-04-27 12:54:21 +02:00
|
|
|
vertex->depth, vertex->Adj_N, spftree->area, spftree->level);
|
2004-09-10 22:48:21 +02:00
|
|
|
else if (isis->debugs & DEBUG_SPF_EVENTS)
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_debug ("ISIS-Spf: no adjacencies do not install route for "
|
2015-11-23 21:44:34 +01:00
|
|
|
"%s depth %d dist %d", vid2string (vertex, buff, sizeof (buff)),
|
2012-03-24 16:35:20 +01:00
|
|
|
vertex->depth, vertex->d_N);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2017-04-27 12:54:21 +02:00
|
|
|
init_spt (struct isis_spftree *spftree, int level, int family)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2004-09-26 18:24:14 +02:00
|
|
|
spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
|
2003-12-23 09:09:43 +01:00
|
|
|
list_delete_all_node (spftree->tents);
|
|
|
|
list_delete_all_node (spftree->paths);
|
|
|
|
spftree->tents->del = spftree->paths->del = NULL;
|
2017-04-27 12:54:21 +02:00
|
|
|
|
|
|
|
spftree->level = level;
|
|
|
|
spftree->family = family;
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static int
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
int retval = ISIS_OK;
|
|
|
|
struct listnode *node;
|
|
|
|
struct isis_vertex *vertex;
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_vertex *root_vertex;
|
2004-09-10 22:48:21 +02:00
|
|
|
struct isis_spftree *spftree = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
u_char lsp_id[ISIS_SYS_ID_LEN + 2];
|
|
|
|
struct isis_lsp *lsp;
|
2005-09-26 20:26:26 +02:00
|
|
|
struct route_table *table = NULL;
|
2012-10-11 13:19:51 +02:00
|
|
|
struct timeval time_now;
|
2012-03-28 08:48:05 +02:00
|
|
|
unsigned long long start_time, end_time;
|
|
|
|
|
|
|
|
/* Get time that can't roll backwards. */
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&time_now);
|
2012-03-28 08:48:05 +02:00
|
|
|
start_time = time_now.tv_sec;
|
2012-10-11 13:19:51 +02:00
|
|
|
start_time = (start_time * 1000000) + time_now.tv_usec;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (family == AF_INET)
|
|
|
|
spftree = area->spftree[level - 1];
|
|
|
|
else if (family == AF_INET6)
|
|
|
|
spftree = area->spftree6[level - 1];
|
|
|
|
assert (spftree);
|
2012-03-24 16:35:20 +01:00
|
|
|
assert (sysid);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2005-09-26 20:26:26 +02:00
|
|
|
/* Make all routes in current route table inactive. */
|
|
|
|
if (family == AF_INET)
|
|
|
|
table = area->route_table[level - 1];
|
|
|
|
else if (family == AF_INET6)
|
|
|
|
table = area->route_table6[level - 1];
|
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_route_invalidate_table (area, table);
|
2005-09-26 20:26:26 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* C.2.5 Step 0
|
|
|
|
*/
|
2017-04-27 12:54:21 +02:00
|
|
|
init_spt (spftree, level, family);
|
2003-12-23 09:09:43 +01:00
|
|
|
/* a) */
|
2017-04-27 12:54:21 +02:00
|
|
|
root_vertex = isis_spf_add_root (spftree, sysid);
|
2003-12-23 09:09:43 +01:00
|
|
|
/* b) */
|
2017-04-27 12:54:21 +02:00
|
|
|
retval = isis_spf_preload_tent (spftree, sysid, root_vertex);
|
2012-03-24 16:35:20 +01:00
|
|
|
if (retval != ISIS_OK)
|
|
|
|
{
|
|
|
|
zlog_warn ("ISIS-Spf: failed to load TENT SPF-root:%s", print_sys_hostname(sysid));
|
|
|
|
goto out;
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* C.2.7 Step 2
|
|
|
|
*/
|
2004-09-10 22:48:21 +02:00
|
|
|
if (listcount (spftree->tents) == 0)
|
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
zlog_warn ("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid));
|
2005-10-01 08:03:04 +02:00
|
|
|
goto out;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (listcount (spftree->tents) > 0)
|
|
|
|
{
|
|
|
|
node = listhead (spftree->tents);
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
vertex = listgetdata (node);
|
2012-03-24 16:35:20 +01:00
|
|
|
|
|
|
|
#ifdef EXTREME_DEBUG
|
|
|
|
zlog_debug ("ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
|
|
|
|
print_sys_hostname (vertex->N.id),
|
|
|
|
vtype2string (vertex->type), vertex->depth, vertex->d_N);
|
|
|
|
#endif /* EXTREME_DEBUG */
|
|
|
|
|
|
|
|
/* Remove from tent list and add to paths list */
|
2004-09-10 22:48:21 +02:00
|
|
|
list_delete_node (spftree->tents, node);
|
2017-04-27 12:54:21 +02:00
|
|
|
add_to_paths (spftree, vertex);
|
|
|
|
if (VTYPE_IS(vertex->type))
|
2012-03-24 16:35:20 +01:00
|
|
|
{
|
2004-09-10 22:48:21 +02:00
|
|
|
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]);
|
2012-03-28 08:48:05 +02:00
|
|
|
if (lsp && lsp->lsp_header->rem_lifetime != 0)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_spf_process_lsp (spftree, lsp, vertex->d_N,
|
|
|
|
vertex->depth, sysid, vertex);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
zlog_warn ("ISIS-Spf: No LSP found for %s",
|
|
|
|
rawlspid_print (lsp_id));
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2005-10-01 08:03:04 +02:00
|
|
|
out:
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_route_validate (area);
|
2012-03-28 08:48:05 +02:00
|
|
|
spftree->runcount++;
|
|
|
|
spftree->last_run_timestamp = time (NULL);
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&time_now);
|
2012-03-28 08:48:05 +02:00
|
|
|
end_time = time_now.tv_sec;
|
2012-10-11 13:19:51 +02:00
|
|
|
end_time = (end_time * 1000000) + time_now.tv_usec;
|
2012-03-28 08:48:05 +02:00
|
|
|
spftree->last_run_duration = end_time - start_time;
|
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2017-02-20 10:51:47 +01:00
|
|
|
static int
|
2017-04-27 12:54:21 +02:00
|
|
|
isis_run_spf_cb (struct thread *thread)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
struct isis_spf_run *run = THREAD_ARG (thread);
|
|
|
|
struct isis_area *area = run->area;
|
|
|
|
int level = run->level;
|
2003-12-23 09:09:43 +01:00
|
|
|
int retval = ISIS_OK;
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
XFREE(MTYPE_ISIS_SPF_RUN, run);
|
|
|
|
area->spf_timer[level - 1] = NULL;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
if (!(area->is_type & level))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
2004-09-19 21:39:26 +02:00
|
|
|
zlog_warn ("ISIS-SPF (%s) area does not share level",
|
|
|
|
area->area_tag);
|
2004-09-10 22:48:21 +02:00
|
|
|
return ISIS_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
2017-04-27 12:54:21 +02:00
|
|
|
zlog_debug ("ISIS-Spf (%s) L%d SPF needed, periodic SPF",
|
|
|
|
area->area_tag, level);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
if (area->ip_circuits)
|
2017-04-27 12:54:21 +02:00
|
|
|
retval = isis_run_spf (area, level, AF_INET, isis->sysid);
|
2017-02-20 10:51:47 +01:00
|
|
|
if (area->ipv6_circuits)
|
2017-04-27 12:54:21 +02:00
|
|
|
retval = isis_run_spf (area, level, AF_INET6, isis->sysid);
|
2004-09-19 21:39:26 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
static struct isis_spf_run*
|
|
|
|
isis_run_spf_arg(struct isis_area *area, int level)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
struct isis_spf_run *run = XMALLOC(MTYPE_ISIS_SPF_RUN, sizeof(*run));
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
run->area = area;
|
|
|
|
run->level = level;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
return run;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
int
|
2003-12-23 09:09:43 +01:00
|
|
|
isis_spf_schedule (struct isis_area *area, int level)
|
|
|
|
{
|
|
|
|
struct isis_spftree *spftree = area->spftree[level - 1];
|
2012-03-24 16:35:20 +01:00
|
|
|
time_t now = time (NULL);
|
2012-03-28 08:48:05 +02:00
|
|
|
int diff = now - spftree->last_run_timestamp;
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
assert (diff >= 0);
|
|
|
|
assert (area->is_type & level);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
|
|
|
zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago",
|
|
|
|
area->area_tag, level, diff);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-02-21 23:52:29 +01:00
|
|
|
if (area->spf_delay_ietf[level - 1])
|
|
|
|
{
|
|
|
|
/* Need to call schedule function also if spf delay is running to
|
|
|
|
* restart holdoff timer - compare draft-ietf-rtgwg-backoff-algo-04 */
|
|
|
|
long delay = spf_backoff_schedule(area->spf_delay_ietf[level -1]);
|
|
|
|
if (area->spf_timer[level - 1])
|
|
|
|
return ISIS_OK;
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
THREAD_TIMER_MSEC_ON(master, area->spf_timer[level-1],
|
|
|
|
isis_run_spf_cb, isis_run_spf_arg(area, level),
|
|
|
|
delay);
|
2017-02-21 23:52:29 +01:00
|
|
|
return ISIS_OK;
|
|
|
|
}
|
|
|
|
|
2017-02-20 10:51:47 +01:00
|
|
|
if (area->spf_timer[level -1])
|
2012-03-24 16:35:20 +01:00
|
|
|
return ISIS_OK;
|
2004-09-19 21:39:26 +02:00
|
|
|
|
2012-03-28 08:48:05 +02:00
|
|
|
/* wait configured min_spf_interval before doing the SPF */
|
|
|
|
if (diff >= area->min_spf_interval[level-1])
|
2004-09-19 21:39:26 +02:00
|
|
|
{
|
2017-02-20 10:51:47 +01:00
|
|
|
int retval = ISIS_OK;
|
2004-09-19 21:39:26 +02:00
|
|
|
|
2017-02-20 10:51:47 +01:00
|
|
|
if (area->ip_circuits)
|
|
|
|
retval = isis_run_spf (area, level, AF_INET, isis->sysid);
|
|
|
|
if (area->ipv6_circuits)
|
|
|
|
retval = isis_run_spf (area, level, AF_INET6, isis->sysid);
|
2004-09-19 21:39:26 +02:00
|
|
|
|
2017-02-20 10:51:47 +01:00
|
|
|
return retval;
|
2004-09-19 21:39:26 +02:00
|
|
|
}
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
THREAD_TIMER_ON (master, area->spf_timer[level-1],
|
|
|
|
isis_run_spf_cb, isis_run_spf_arg(area, level),
|
|
|
|
area->min_spf_interval[level-1] - diff);
|
2012-03-24 16:35:20 +01:00
|
|
|
|
2012-03-28 08:48:05 +02:00
|
|
|
if (isis->debugs & DEBUG_SPF_EVENTS)
|
2017-02-20 10:51:47 +01:00
|
|
|
zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now",
|
|
|
|
area->area_tag, level, area->min_spf_interval[level-1] - diff);
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2017-02-20 10:51:47 +01:00
|
|
|
return ISIS_OK;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2005-01-18 14:53:33 +01:00
|
|
|
static void
|
2012-03-24 16:35:20 +01:00
|
|
|
isis_print_paths (struct vty *vty, struct list *paths, u_char *root_sysid)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *node;
|
2012-03-24 16:35:20 +01:00
|
|
|
struct listnode *anode;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct isis_vertex *vertex;
|
|
|
|
struct isis_adjacency *adj;
|
2015-11-23 21:44:34 +01:00
|
|
|
char buff[PREFIX2STR_BUFFER];
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out (vty, "Vertex Type Metric "
|
|
|
|
"Next-Hop Interface Parent%s", VTY_NEWLINE);
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) {
|
|
|
|
if (memcmp (vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) {
|
|
|
|
vty_out (vty, "%-20s %-12s %-6s", print_sys_hostname (root_sysid),
|
|
|
|
"", "");
|
|
|
|
vty_out (vty, "%-30s", "");
|
|
|
|
} else {
|
|
|
|
int rows = 0;
|
2015-11-23 21:44:34 +01:00
|
|
|
vty_out (vty, "%-20s %-12s %-6u ", vid2string (vertex, buff, sizeof (buff)),
|
2012-03-24 16:35:20 +01:00
|
|
|
vtype2string (vertex->type), vertex->d_N);
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (vertex->Adj_N, anode, adj)) {
|
|
|
|
if (adj) {
|
|
|
|
if (rows) {
|
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
|
|
|
vty_out (vty, "%-20s %-12s %-6s ", "", "", "");
|
|
|
|
}
|
|
|
|
vty_out (vty, "%-20s %-9s ",
|
|
|
|
print_sys_hostname (adj->sysid),
|
|
|
|
adj->circuit->interface->name);
|
|
|
|
++rows;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rows == 0)
|
|
|
|
vty_out (vty, "%-30s ", "");
|
|
|
|
}
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
/* Print list of parents for the ECMP DAG */
|
|
|
|
if (listcount (vertex->parents) > 0) {
|
|
|
|
struct listnode *pnode;
|
|
|
|
struct isis_vertex *pvertex;
|
|
|
|
int rows = 0;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (vertex->parents, pnode, pvertex)) {
|
|
|
|
if (rows) {
|
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
|
|
|
vty_out (vty, "%-72s", "");
|
|
|
|
}
|
|
|
|
vty_out (vty, "%s(%d)",
|
2015-11-23 21:44:34 +01:00
|
|
|
vid2string (pvertex, buff, sizeof (buff)), pvertex->type);
|
2012-03-24 16:35:20 +01:00
|
|
|
++rows;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
} else {
|
|
|
|
vty_out (vty, " NULL ");
|
|
|
|
}
|
|
|
|
|
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (show_isis_topology,
|
|
|
|
show_isis_topology_cmd,
|
2017-04-27 12:54:21 +02:00
|
|
|
"show isis topology [<level-1|level-2>]",
|
2003-12-23 09:09:43 +01:00
|
|
|
SHOW_STR
|
|
|
|
"IS-IS information\n"
|
2017-04-27 12:54:21 +02:00
|
|
|
"IS-IS paths to Intermediate Systems\n"
|
|
|
|
"Paths to all level-1 routers in the area\n"
|
|
|
|
"Paths to all level-2 routers in the domain\n")
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
int levels;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct listnode *node;
|
|
|
|
struct isis_area *area;
|
2017-04-27 12:54:21 +02:00
|
|
|
|
|
|
|
if (argc < 4)
|
|
|
|
levels = ISIS_LEVEL1|ISIS_LEVEL2;
|
|
|
|
else if (!strcmp(argv[3]->arg, "level-1"))
|
|
|
|
levels = ISIS_LEVEL1;
|
|
|
|
else
|
|
|
|
levels = ISIS_LEVEL2;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (!isis->area_list || isis->area_list->count == 0)
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
|
|
|
|
VTY_NEWLINE);
|
|
|
|
|
2017-04-27 12:54:21 +02:00
|
|
|
for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
2017-04-27 12:54:21 +02:00
|
|
|
if ((level & levels) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (area->ip_circuits > 0 && area->spftree[level-1]
|
|
|
|
&& area->spftree[level-1]->paths->count > 0)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s",
|
2017-04-27 12:54:21 +02:00
|
|
|
level, VTY_NEWLINE);
|
|
|
|
isis_print_paths (vty, area->spftree[level-1]->paths, isis->sysid);
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2017-04-27 12:54:21 +02:00
|
|
|
if (area->ipv6_circuits > 0 && area->spftree6[level-1]
|
|
|
|
&& area->spftree6[level-1]->paths->count > 0)
|
2004-09-10 22:48:21 +02:00
|
|
|
{
|
|
|
|
vty_out (vty,
|
|
|
|
"IS-IS paths to level-%d routers that speak IPv6%s",
|
2017-04-27 12:54:21 +02:00
|
|
|
level, VTY_NEWLINE);
|
|
|
|
isis_print_paths (vty, area->spftree6[level-1]->paths, isis->sysid);
|
2012-03-24 16:35:20 +01:00
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
|
|
|
}
|
2012-03-24 16:35:20 +01:00
|
|
|
|
|
|
|
vty_out (vty, "%s", VTY_NEWLINE);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
isis_spf_cmds_init ()
|
|
|
|
{
|
|
|
|
install_element (VIEW_NODE, &show_isis_topology_cmd);
|
|
|
|
}
|