version 1.1, 2012/02/21 17:26:11
|
version 1.1.1.2, 2012/10/09 09:22:28
|
Line 36
|
Line 36
|
|
|
#include "isis_constants.h" |
#include "isis_constants.h" |
#include "isis_common.h" |
#include "isis_common.h" |
|
#include "isis_flags.h" |
#include "dict.h" |
#include "dict.h" |
#include "isisd.h" |
#include "isisd.h" |
#include "isis_misc.h" |
#include "isis_misc.h" |
Line 49
|
Line 50
|
#include "isis_route.h" |
#include "isis_route.h" |
#include "isis_csm.h" |
#include "isis_csm.h" |
|
|
extern struct isis *isis; |
|
extern struct thread_master *master; |
|
extern struct host host; |
|
|
|
int isis_run_spf_l1 (struct thread *thread); |
int isis_run_spf_l1 (struct thread *thread); |
int isis_run_spf_l2 (struct thread *thread); |
int isis_run_spf_l2 (struct thread *thread); |
|
|
Line 113 remove_excess_adjs (struct list *adjs)
|
Line 110 remove_excess_adjs (struct list *adjs)
|
return; |
return; |
} |
} |
|
|
#ifdef EXTREME_DEBUG |
|
static const char * |
static const char * |
vtype2string (enum vertextype vtype) |
vtype2string (enum vertextype vtype) |
{ |
{ |
Line 164 vid2string (struct isis_vertex *vertex, u_char * buff)
|
Line 160 vid2string (struct isis_vertex *vertex, u_char * buff)
|
{ |
{ |
case VTYPE_PSEUDO_IS: |
case VTYPE_PSEUDO_IS: |
case VTYPE_PSEUDO_TE_IS: |
case VTYPE_PSEUDO_TE_IS: |
return rawlspid_print (vertex->N.id); | return print_sys_hostname (vertex->N.id); |
break; |
break; |
case VTYPE_NONPSEUDO_IS: |
case VTYPE_NONPSEUDO_IS: |
case VTYPE_NONPSEUDO_TE_IS: |
case VTYPE_NONPSEUDO_TE_IS: |
case VTYPE_ES: |
case VTYPE_ES: |
return sysid_print (vertex->N.id); | return print_sys_hostname (vertex->N.id); |
break; |
break; |
case VTYPE_IPREACH_INTERNAL: |
case VTYPE_IPREACH_INTERNAL: |
case VTYPE_IPREACH_EXTERNAL: |
case VTYPE_IPREACH_EXTERNAL: |
Line 186 vid2string (struct isis_vertex *vertex, u_char * buff)
|
Line 182 vid2string (struct isis_vertex *vertex, u_char * buff)
|
|
|
return (char *) buff; |
return (char *) buff; |
} |
} |
#endif /* EXTREME_DEBUG */ |
|
|
|
static struct isis_spftree * | static struct isis_vertex * |
isis_spftree_new () | isis_vertex_new (void *id, enum vertextype vtype) |
{ |
{ |
struct isis_spftree *tree; | struct isis_vertex *vertex; |
|
|
tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree)); | vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex)); |
if (tree == NULL) | if (vertex == NULL) |
{ |
{ |
zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!"); | zlog_err ("isis_vertex_new Out of memory!"); |
return NULL; |
return NULL; |
} |
} |
|
|
tree->tents = list_new (); | vertex->type = vtype; |
tree->paths = list_new (); | switch (vtype) |
return tree; | { |
| 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: |
| #endif /* HAVE_IPV6 */ |
| memcpy (&vertex->N.prefix, (struct prefix *) id, |
| sizeof (struct prefix)); |
| break; |
| default: |
| zlog_err ("WTF!"); |
| } |
| |
| vertex->Adj_N = list_new (); |
| vertex->parents = list_new (); |
| vertex->children = list_new (); |
| |
| return vertex; |
} |
} |
|
|
static void |
static void |
isis_vertex_del (struct isis_vertex *vertex) |
isis_vertex_del (struct isis_vertex *vertex) |
{ |
{ |
list_delete (vertex->Adj_N); |
list_delete (vertex->Adj_N); |
|
vertex->Adj_N = NULL; |
|
list_delete (vertex->parents); |
|
vertex->parents = NULL; |
|
list_delete (vertex->children); |
|
vertex->children = NULL; |
|
|
|
memset(vertex, 0, sizeof(struct isis_vertex)); |
XFREE (MTYPE_ISIS_VERTEX, vertex); |
XFREE (MTYPE_ISIS_VERTEX, vertex); |
|
|
return; |
return; |
} |
} |
|
|
#if 0 /* HT: Not used yet. */ |
|
static void |
static void |
|
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; |
|
tree->last_run_timestamp = 0; |
|
tree->last_run_duration = 0; |
|
tree->runcount = 0; |
|
tree->pending = 0; |
|
return tree; |
|
} |
|
|
|
void |
isis_spftree_del (struct isis_spftree *spftree) |
isis_spftree_del (struct isis_spftree *spftree) |
{ |
{ |
|
THREAD_TIMER_OFF (spftree->t_spf); |
|
|
spftree->tents->del = (void (*)(void *)) isis_vertex_del; |
spftree->tents->del = (void (*)(void *)) isis_vertex_del; |
list_delete (spftree->tents); |
list_delete (spftree->tents); |
|
spftree->tents = NULL; |
|
|
spftree->paths->del = (void (*)(void *)) isis_vertex_del; |
spftree->paths->del = (void (*)(void *)) isis_vertex_del; |
list_delete (spftree->paths); |
list_delete (spftree->paths); |
|
spftree->paths = NULL; |
|
|
XFREE (MTYPE_ISIS_SPFTREE, spftree); |
XFREE (MTYPE_ISIS_SPFTREE, spftree); |
|
|
return; |
return; |
} |
} |
#endif |
|
|
|
void |
void |
|
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; |
|
} |
|
|
|
void |
spftree_area_init (struct isis_area *area) |
spftree_area_init (struct isis_area *area) |
{ |
{ |
if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL) | if (area->is_type & IS_LEVEL_1) |
{ | { |
area->spftree[0] = isis_spftree_new (); | if (area->spftree[0] == NULL) |
| area->spftree[0] = isis_spftree_new (area); |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
area->spftree6[0] = isis_spftree_new (); | if (area->spftree6[0] == NULL) |
| area->spftree6[0] = isis_spftree_new (area); |
#endif |
#endif |
|
} |
|
|
/* thread_add_timer (master, isis_run_spf_l1, area, | if (area->is_type & IS_LEVEL_2) |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */ | { |
} | if (area->spftree[1] == NULL) |
| area->spftree[1] = isis_spftree_new (area); |
if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL) | |
{ | |
area->spftree[1] = isis_spftree_new (); | |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
area->spftree6[1] = isis_spftree_new (); | if (area->spftree6[1] == NULL) |
| area->spftree6[1] = isis_spftree_new (area); |
#endif |
#endif |
/* thread_add_timer (master, isis_run_spf_l2, area, | } |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */ | |
} | |
|
|
return; |
return; |
} |
} |
|
|
static struct isis_vertex * | void |
isis_vertex_new (void *id, enum vertextype vtype) | spftree_area_del (struct isis_area *area) |
{ |
{ |
struct isis_vertex *vertex; | if (area->is_type & IS_LEVEL_1) |
| { |
vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex)); | if (area->spftree[0] != NULL) |
if (vertex == NULL) | |
{ |
{ |
zlog_err ("isis_vertex_new Out of memory!"); | isis_spftree_del (area->spftree[0]); |
return NULL; | area->spftree[0] = NULL; |
} |
} |
|
#ifdef HAVE_IPV6 |
|
if (area->spftree6[0]) |
|
{ |
|
isis_spftree_del (area->spftree6[0]); |
|
area->spftree6[0] = NULL; |
|
} |
|
#endif |
|
} |
|
|
vertex->type = vtype; | if (area->is_type & IS_LEVEL_2) |
switch (vtype) | { |
| if (area->spftree[1] != NULL) |
{ |
{ |
case VTYPE_ES: | isis_spftree_del (area->spftree[1]); |
case VTYPE_NONPSEUDO_IS: | area->spftree[1] = NULL; |
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 |
#ifdef HAVE_IPV6 |
case VTYPE_IP6REACH_INTERNAL: | if (area->spftree[1] != NULL) |
case VTYPE_IP6REACH_EXTERNAL: | { |
#endif /* HAVE_IPV6 */ | isis_spftree_del (area->spftree6[1]); |
memcpy (&vertex->N.prefix, (struct prefix *) id, | area->spftree6[1] = NULL; |
sizeof (struct prefix)); | |
break; | |
default: | |
zlog_err ("WTF!"); | |
} |
} |
|
#endif |
|
} |
|
|
vertex->Adj_N = list_new (); | return; |
| } |
|
|
return vertex; | 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); |
| #ifdef HAVE_IPV6 |
| if (area->spftree6[0] != NULL) |
| isis_spftree_adj_del (area->spftree6[0], adj); |
| #endif |
| } |
| |
| if (area->is_type & IS_LEVEL_2) |
| { |
| if (area->spftree[1] != NULL) |
| isis_spftree_adj_del (area->spftree[1], adj); |
| #ifdef HAVE_IPV6 |
| if (area->spftree6[1] != NULL) |
| isis_spftree_adj_del (area->spftree6[1], adj); |
| #endif |
| } |
| |
| return; |
} |
} |
|
|
|
/* |
|
* Find the system LSP: returns the LSP in our LSP database |
|
* associated with the given system ID. |
|
*/ |
|
static struct isis_lsp * |
|
isis_root_system_lsp (struct isis_area *area, int level, u_char *sysid) |
|
{ |
|
struct isis_lsp *lsp; |
|
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
|
|
|
memcpy (lspid, sysid, ISIS_SYS_ID_LEN); |
|
LSP_PSEUDO_ID (lspid) = 0; |
|
LSP_FRAGMENT (lspid) = 0; |
|
lsp = lsp_search (lspid, area->lspdb[level - 1]); |
|
if (lsp && lsp->lsp_header->rem_lifetime != 0) |
|
return lsp; |
|
return NULL; |
|
} |
|
|
/* |
/* |
* Add this IS to the root of SPT |
* Add this IS to the root of SPT |
*/ |
*/ |
static void | static struct isis_vertex * |
isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area, | isis_spf_add_root (struct isis_spftree *spftree, int level, u_char *sysid) |
int level) | |
{ |
{ |
struct isis_vertex *vertex; |
struct isis_vertex *vertex; |
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
|
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
u_char buff[BUFSIZ]; |
u_char buff[BUFSIZ]; |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); |
|
LSP_PSEUDO_ID (lspid) = 0; |
|
LSP_FRAGMENT (lspid) = 0; |
|
|
|
lsp = lsp_search (lspid, area->lspdb[level - 1]); | lsp = isis_root_system_lsp (spftree->area, level, sysid); |
| |
if (lsp == NULL) |
if (lsp == NULL) |
zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level); |
zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level); |
|
|
if (!area->oldmetric) | if (!spftree->area->oldmetric) |
vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_TE_IS); | vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_TE_IS); |
else |
else |
vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS); | vertex = isis_vertex_new (sysid, VTYPE_NONPSEUDO_IS); |
|
|
vertex->lsp = lsp; |
|
|
|
listnode_add (spftree->paths, vertex); |
listnode_add (spftree->paths, vertex); |
|
|
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
Line 338 isis_spf_add_self (struct isis_spftree *spftree, struc
|
Line 450 isis_spf_add_self (struct isis_spftree *spftree, struc
|
vertex->depth, vertex->d_N); |
vertex->depth, vertex->d_N); |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
|
|
return; | return vertex; |
} |
} |
|
|
static struct isis_vertex * |
static struct isis_vertex * |
Line 390 isis_find_vertex (struct list *list, void *id, enum ve
|
Line 502 isis_find_vertex (struct list *list, void *id, enum ve
|
*/ |
*/ |
static struct isis_vertex * |
static struct isis_vertex * |
isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, |
isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, |
void *id, struct isis_adjacency *adj, u_int32_t cost, | void *id, uint32_t cost, int depth, int family, |
int depth, int family) | struct isis_adjacency *adj, struct isis_vertex *parent) |
{ |
{ |
struct isis_vertex *vertex, *v; |
struct isis_vertex *vertex, *v; |
struct listnode *node; |
struct listnode *node; |
|
struct isis_adjacency *parent_adj; |
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
u_char buff[BUFSIZ]; |
u_char buff[BUFSIZ]; |
#endif |
#endif |
|
|
|
assert (isis_find_vertex (spftree->paths, id, vtype) == NULL); |
|
assert (isis_find_vertex (spftree->tents, id, vtype) == NULL); |
vertex = isis_vertex_new (id, vtype); |
vertex = isis_vertex_new (id, vtype); |
vertex->d_N = cost; |
vertex->d_N = cost; |
vertex->depth = depth; |
vertex->depth = depth; |
|
|
if (adj) | 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) { |
listnode_add (vertex->Adj_N, adj); |
listnode_add (vertex->Adj_N, adj); |
|
} |
|
|
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d", | zlog_debug ("ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d", |
| print_sys_hostname (vertex->N.id), |
vtype2string (vertex->type), vid2string (vertex, buff), |
vtype2string (vertex->type), vid2string (vertex, buff), |
vertex->depth, vertex->d_N); | vertex->depth, vertex->d_N, listcount(vertex->Adj_N)); |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
listnode_add (spftree->tents, vertex); | |
if (list_isempty (spftree->tents)) |
if (list_isempty (spftree->tents)) |
{ |
{ |
listnode_add (spftree->tents, vertex); |
listnode_add (spftree->tents, vertex); |
return vertex; |
return vertex; |
} |
} |
| |
/* XXX: This cant use the standard ALL_LIST_ELEMENT macro */ | /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */ |
for (node = listhead (spftree->tents); node; node = listnextnode (node)) |
for (node = listhead (spftree->tents); node; node = listnextnode (node)) |
{ |
{ |
v = listgetdata (node); |
v = listgetdata (node); |
Line 426 isis_spf_add2tent (struct isis_spftree *spftree, enum
|
Line 553 isis_spf_add2tent (struct isis_spftree *spftree, enum
|
list_add_node_prev (spftree->tents, node, vertex); |
list_add_node_prev (spftree->tents, node, vertex); |
break; |
break; |
} |
} |
else if (v->d_N == vertex->d_N) | else if (v->d_N == vertex->d_N && v->type > vertex->type) |
{ |
{ |
/* Tie break, add according to type */ |
/* Tie break, add according to type */ |
while (v && v->d_N == vertex->d_N && v->type > vertex->type) | list_add_node_prev (spftree->tents, node, vertex); |
{ | |
if (v->type > vertex->type) | |
{ | |
break; | |
} | |
/* XXX: this seems dubious, node is the loop iterator */ | |
node = listnextnode (node); | |
(node) ? (v = listgetdata (node)) : (v = NULL); | |
} | |
list_add_node_prev (spftree->tents, node, vertex); | |
break; |
break; |
} |
} |
else if (node->next == NULL) |
|
{ |
|
list_add_node_next (spftree->tents, node, vertex); |
|
break; |
|
} |
|
} |
} |
|
|
|
if (node == NULL) |
|
listnode_add (spftree->tents, vertex); |
|
|
return vertex; |
return vertex; |
} |
} |
|
|
static struct isis_vertex * | static void |
isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype, |
isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype, |
void *id, struct isis_adjacency *adj, u_int32_t cost, | void *id, struct isis_adjacency *adj, uint32_t cost, |
int family) | int family, struct isis_vertex *parent) |
{ |
{ |
struct isis_vertex *vertex; |
struct isis_vertex *vertex; |
|
|
Line 470 isis_spf_add_local (struct isis_spftree *spftree, enum
|
Line 586 isis_spf_add_local (struct isis_spftree *spftree, enum
|
/* d) */ |
/* d) */ |
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) |
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) |
remove_excess_adjs (vertex->Adj_N); |
remove_excess_adjs (vertex->Adj_N); |
|
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; |
} |
} |
/* f) */ | else if (vertex->d_N < cost) |
else if (vertex->d_N > cost) | |
{ |
{ |
listnode_delete (spftree->tents, vertex); | /* e) do nothing */ |
goto add2tent; | return; |
} |
} |
/* e) do nothing */ | else { /* vertex->d_N > cost */ |
return vertex; | /* 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); |
| } |
} |
} |
|
|
add2tent: | isis_spf_add2tent (spftree, vtype, id, cost, 1, family, adj, parent); |
return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family); | return; |
} |
} |
|
|
static void |
static void |
process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, |
process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, |
u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj, | uint32_t dist, uint16_t depth, int family, |
int family) | struct isis_vertex *parent) |
{ |
{ |
struct isis_vertex *vertex; |
struct isis_vertex *vertex; |
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
u_char buff[255]; |
u_char buff[255]; |
#endif |
#endif |
|
|
|
assert (spftree && parent); |
|
|
|
/* RFC3787 section 5.1 */ |
|
if (spftree->area->newmetric == 1) |
|
{ |
|
if (dist > MAX_WIDE_PATH_METRIC) |
|
return; |
|
} |
/* C.2.6 b) */ |
/* C.2.6 b) */ |
if (dist > MAX_PATH_METRIC) | else if (spftree->area->oldmetric == 1) |
return; | { |
| if (dist > MAX_NARROW_PATH_METRIC) |
| return; |
| } |
| |
/* c) */ |
/* c) */ |
vertex = isis_find_vertex (spftree->paths, id, vtype); |
vertex = isis_find_vertex (spftree->paths, id, vtype); |
if (vertex) |
if (vertex) |
{ |
{ |
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
zlog_debug ("ISIS-Spf: process_N %s %s dist %d already found from PATH", | zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d already found from PATH", |
| print_sys_hostname (vertex->N.id), |
vtype2string (vtype), vid2string (vertex, buff), dist); |
vtype2string (vtype), vid2string (vertex, buff), dist); |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
assert (dist >= vertex->d_N); |
assert (dist >= vertex->d_N); |
Line 516 process_N (struct isis_spftree *spftree, enum vertexty
|
Line 657 process_N (struct isis_spftree *spftree, enum vertexty
|
{ |
{ |
/* 1) */ |
/* 1) */ |
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
zlog_debug ("ISIS-Spf: process_N %s %s dist %d", | zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d", |
vtype2string (vtype), vid2string (vertex, buff), dist); | print_sys_hostname (vertex->N.id), |
| vtype2string (vtype), vid2string (vertex, buff), dist, |
| (parent ? print_sys_hostname (parent->N.id) : "null"), |
| (parent ? listcount (parent->Adj_N) : 0)); |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
if (vertex->d_N == dist) |
if (vertex->d_N == dist) |
{ |
{ |
if (adj) | struct listnode *node; |
listnode_add (vertex->Adj_N, adj); | 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); |
/* 2) */ |
/* 2) */ |
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) |
if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) |
remove_excess_adjs (vertex->Adj_N); |
remove_excess_adjs (vertex->Adj_N); |
|
if (listnode_lookup (vertex->parents, parent) == NULL) |
|
listnode_add (vertex->parents, parent); |
|
if (listnode_lookup (parent->children, vertex) == NULL) |
|
listnode_add (parent->children, vertex); |
/* 3) */ |
/* 3) */ |
return; |
return; |
} |
} |
Line 536 process_N (struct isis_spftree *spftree, enum vertexty
|
Line 687 process_N (struct isis_spftree *spftree, enum vertexty
|
} |
} |
else |
else |
{ |
{ |
|
struct listnode *pnode, *pnextnode; |
|
struct isis_vertex *pvertex; |
listnode_delete (spftree->tents, vertex); |
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); |
} |
} |
} |
} |
|
|
isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family); | #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 */ |
| |
| isis_spf_add2tent (spftree, vtype, id, dist, depth, family, NULL, parent); |
return; |
return; |
} |
} |
|
|
Line 549 process_N (struct isis_spftree *spftree, enum vertexty
|
Line 712 process_N (struct isis_spftree *spftree, enum vertexty
|
*/ |
*/ |
static int |
static int |
isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, |
isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, |
uint32_t cost, uint16_t depth, int family) | uint32_t cost, uint16_t depth, int family, |
| u_char *root_sysid, struct isis_vertex *parent) |
{ |
{ |
struct listnode *node, *fragnode = NULL; |
struct listnode *node, *fragnode = NULL; |
u_int16_t dist; | uint32_t dist; |
struct is_neigh *is_neigh; |
struct is_neigh *is_neigh; |
struct te_is_neigh *te_is_neigh; |
struct te_is_neigh *te_is_neigh; |
struct ipv4_reachability *ipreach; |
struct ipv4_reachability *ipreach; |
Line 562 isis_spf_process_lsp (struct isis_spftree *spftree, st
|
Line 726 isis_spf_process_lsp (struct isis_spftree *spftree, st
|
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
struct ipv6_reachability *ip6reach; |
struct ipv6_reachability *ip6reach; |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
static const u_char null_sysid[ISIS_SYS_ID_LEN]; |
|
|
| if (!speaks (lsp->tlv_data.nlpids, family)) |
if (!lsp->adj) | |
return ISIS_WARNING; | |
if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) | |
return ISIS_OK; |
return ISIS_OK; |
|
|
lspfragloop: |
lspfragloop: |
if (lsp->lsp_header->seq_num == 0) |
if (lsp->lsp_header->seq_num == 0) |
{ |
{ |
zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num" | zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num - ignore"); |
" - do not process"); | |
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
|
|
|
#ifdef EXTREME_DEBUG |
|
zlog_debug ("ISIS-Spf: process_lsp %s", print_sys_hostname(lsp->lsp_header->lsp_id)); |
|
#endif /* EXTREME_DEBUG */ |
|
|
if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) |
if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) |
|
{ |
|
if (lsp->tlv_data.is_neighs) |
{ |
{ |
if (lsp->tlv_data.is_neighs) | for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) |
{ | { |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) | /* C.2.6 a) */ |
{ | /* Two way connectivity */ |
/* C.2.6 a) */ | if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) |
/* Two way connectivity */ | continue; |
if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) | if (!memcmp (is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN)) |
continue; | continue; |
dist = cost + is_neigh->metrics.metric_default; | dist = cost + is_neigh->metrics.metric_default; |
vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS | vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS |
: VTYPE_NONPSEUDO_IS; | : VTYPE_NONPSEUDO_IS; |
process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, | process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, |
depth + 1, lsp->adj, family); | depth + 1, family, parent); |
} | } |
} | } |
if (lsp->tlv_data.te_is_neighs) | if (lsp->tlv_data.te_is_neighs) |
{ | { |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, | for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, |
te_is_neigh)) | te_is_neigh)) |
{ | { |
uint32_t metric; | if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) |
if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) | continue; |
continue; | if (!memcmp (te_is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN)) |
memcpy (&metric, te_is_neigh->te_metric, 3); | continue; |
dist = cost + ntohl (metric << 8); | dist = cost + GET_TE_METRIC(te_is_neigh); |
vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS | vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS |
: VTYPE_NONPSEUDO_TE_IS; | : VTYPE_NONPSEUDO_TE_IS; |
process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, | process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, |
depth + 1, lsp->adj, family); | depth + 1, family, parent); |
} | } |
} | } |
if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) | } |
{ | |
prefix.family = AF_INET; | |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, | |
node, ipreach)) | |
{ | |
dist = cost + ipreach->metrics.metric_default; | |
vtype = VTYPE_IPREACH_INTERNAL; | |
prefix.u.prefix4 = ipreach->prefix; | |
prefix.prefixlen = ip_masklen (ipreach->mask); | |
process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, | |
lsp->adj, family); | |
} | |
} | |
|
|
if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) | if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) |
{ | { |
prefix.family = AF_INET; | prefix.family = AF_INET; |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, | for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach)) |
node, ipreach)) | { |
{ | dist = cost + ipreach->metrics.metric_default; |
dist = cost + ipreach->metrics.metric_default; | vtype = VTYPE_IPREACH_INTERNAL; |
vtype = VTYPE_IPREACH_EXTERNAL; | prefix.u.prefix4 = ipreach->prefix; |
prefix.u.prefix4 = ipreach->prefix; | prefix.prefixlen = ip_masklen (ipreach->mask); |
prefix.prefixlen = ip_masklen (ipreach->mask); | apply_mask (&prefix); |
process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, | process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, |
lsp->adj, family); | family, parent); |
} | } |
} | } |
if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs) | if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) |
{ | { |
prefix.family = AF_INET; | prefix.family = AF_INET; |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs, | for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach)) |
node, te_ipv4_reach)) | { |
{ | dist = cost + ipreach->metrics.metric_default; |
dist = cost + ntohl (te_ipv4_reach->te_metric); | vtype = VTYPE_IPREACH_EXTERNAL; |
vtype = VTYPE_IPREACH_TE; | prefix.u.prefix4 = ipreach->prefix; |
prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start, | prefix.prefixlen = ip_masklen (ipreach->mask); |
te_ipv4_reach->control); | apply_mask (&prefix); |
prefix.prefixlen = (te_ipv4_reach->control & 0x3F); | process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, |
process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, | family, parent); |
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); |
| apply_mask (&prefix); |
| process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, |
| family, parent); |
| } |
| } |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs) | if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs) |
{ | { |
prefix.family = AF_INET6; | prefix.family = AF_INET6; |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, | for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach)) |
node, ip6reach)) | { |
{ | dist = cost + ip6reach->metric; |
dist = cost + ip6reach->metric; | vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ? |
vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ? | VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL; |
VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL; | prefix.prefixlen = ip6reach->prefix_len; |
prefix.prefixlen = ip6reach->prefix_len; | memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, |
memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, | PSIZE (ip6reach->prefix_len)); |
PSIZE (ip6reach->prefix_len)); | apply_mask (&prefix); |
process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, | process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, |
lsp->adj, family); | family, parent); |
} | |
} | |
#endif /* HAVE_IPV6 */ | |
} |
} |
|
} |
|
#endif /* HAVE_IPV6 */ |
|
|
if (fragnode == NULL) |
if (fragnode == NULL) |
fragnode = listhead (lsp->lspu.frags); |
fragnode = listhead (lsp->lspu.frags); |
Line 690 lspfragloop:
|
Line 858 lspfragloop:
|
|
|
static int |
static int |
isis_spf_process_pseudo_lsp (struct isis_spftree *spftree, |
isis_spf_process_pseudo_lsp (struct isis_spftree *spftree, |
struct isis_lsp *lsp, uint16_t cost, | struct isis_lsp *lsp, uint32_t cost, |
uint16_t depth, int family) | uint16_t depth, int family, |
| u_char *root_sysid, |
| struct isis_vertex *parent) |
{ |
{ |
struct listnode *node, *fragnode = NULL; |
struct listnode *node, *fragnode = NULL; |
struct is_neigh *is_neigh; |
struct is_neigh *is_neigh; |
struct te_is_neigh *te_is_neigh; |
struct te_is_neigh *te_is_neigh; |
enum vertextype vtype; |
enum vertextype vtype; |
|
uint32_t dist; |
|
|
pseudofragloop: |
pseudofragloop: |
|
|
Line 707 pseudofragloop:
|
Line 878 pseudofragloop:
|
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
|
|
|
#ifdef EXTREME_DEBUG |
|
zlog_debug ("ISIS-Spf: process_pseudo_lsp %s", |
|
print_sys_hostname(lsp->lsp_header->lsp_id)); |
|
#endif /* EXTREME_DEBUG */ |
|
|
|
/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */ |
|
|
if (lsp->tlv_data.is_neighs) |
if (lsp->tlv_data.is_neighs) |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) |
{ |
{ |
vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS |
|
: VTYPE_NONPSEUDO_IS; |
|
/* Two way connectivity */ |
/* Two way connectivity */ |
if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) | if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) |
continue; |
continue; |
if (isis_find_vertex | dist = cost + is_neigh->metrics.metric_default; |
(spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL | vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS |
&& isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id, | : VTYPE_NONPSEUDO_IS; |
vtype) == NULL) | process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, |
{ | depth + 1, family, parent); |
/* 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) |
if (lsp->tlv_data.te_is_neighs) |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) |
for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) |
{ |
{ |
vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS |
|
: VTYPE_NONPSEUDO_TE_IS; |
|
/* Two way connectivity */ |
/* Two way connectivity */ |
if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) | if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) |
continue; |
continue; |
if (isis_find_vertex | dist = cost + GET_TE_METRIC(te_is_neigh); |
(spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL | vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS |
&& isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id, | : VTYPE_NONPSEUDO_TE_IS; |
vtype) == NULL) | process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, |
{ | depth + 1, family, parent); |
/* C.2.5 i) */ | |
isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj, | |
cost, depth, family); | |
} | |
} |
} |
|
|
if (fragnode == NULL) |
if (fragnode == NULL) |
Line 759 pseudofragloop:
|
Line 925 pseudofragloop:
|
} |
} |
|
|
static int |
static int |
isis_spf_preload_tent (struct isis_spftree *spftree, | isis_spf_preload_tent (struct isis_spftree *spftree, int level, |
struct isis_area *area, int level, int family) | int family, u_char *root_sysid, |
| struct isis_vertex *parent) |
{ |
{ |
struct isis_vertex *vertex; |
|
struct isis_circuit *circuit; |
struct isis_circuit *circuit; |
struct listnode *cnode, *anode, *ipnode; |
struct listnode *cnode, *anode, *ipnode; |
struct isis_adjacency *adj; |
struct isis_adjacency *adj; |
Line 773 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 939 isis_spf_preload_tent (struct isis_spftree *spftree,
|
struct prefix prefix; |
struct prefix prefix; |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
|
static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2]; |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
struct prefix_ipv6 *ipv6; |
struct prefix_ipv6 *ipv6; |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
|
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) | for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit)) |
{ |
{ |
if (circuit->state != C_STATE_UP) |
if (circuit->state != C_STATE_UP) |
continue; |
continue; |
if (!(circuit->circuit_is_type & level)) | if (!(circuit->is_type & level)) |
continue; |
continue; |
if (family == AF_INET && !circuit->ip_router) |
if (family == AF_INET && !circuit->ip_router) |
continue; |
continue; |
Line 799 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 966 isis_spf_preload_tent (struct isis_spftree *spftree,
|
{ |
{ |
prefix.u.prefix4 = ipv4->prefix; |
prefix.u.prefix4 = ipv4->prefix; |
prefix.prefixlen = ipv4->prefixlen; |
prefix.prefixlen = ipv4->prefixlen; |
|
apply_mask (&prefix); |
isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix, |
isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix, |
NULL, 0, family); | NULL, 0, family, parent); |
} |
} |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
Line 811 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 979 isis_spf_preload_tent (struct isis_spftree *spftree,
|
{ |
{ |
prefix.prefixlen = ipv6->prefixlen; |
prefix.prefixlen = ipv6->prefixlen; |
prefix.u.prefix6 = ipv6->prefix; |
prefix.u.prefix6 = ipv6->prefix; |
|
apply_mask (&prefix); |
isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL, |
isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL, |
&prefix, NULL, 0, family); | &prefix, NULL, 0, family, parent); |
} |
} |
} |
} |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
Line 832 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 1001 isis_spf_preload_tent (struct isis_spftree *spftree,
|
level, circuit->interface->name); |
level, circuit->interface->name); |
continue; |
continue; |
} |
} |
anode = listhead (adj_list); | for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj)) |
while (anode) | |
{ |
{ |
adj = listgetdata (anode); |
|
if (!speaks (&adj->nlpids, family)) |
if (!speaks (&adj->nlpids, family)) |
{ |
|
anode = listnextnode (anode); |
|
continue; |
continue; |
} |
|
switch (adj->sys_type) |
switch (adj->sys_type) |
{ |
{ |
case ISIS_SYSTYPE_ES: |
case ISIS_SYSTYPE_ES: |
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, |
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, |
circuit->te_metric[level - 1], family); | circuit->te_metric[level - 1], |
| family, parent); |
break; |
break; |
case ISIS_SYSTYPE_IS: |
case ISIS_SYSTYPE_IS: |
case ISIS_SYSTYPE_L1_IS: |
case ISIS_SYSTYPE_L1_IS: |
case ISIS_SYSTYPE_L2_IS: |
case ISIS_SYSTYPE_L2_IS: |
vertex = | isis_spf_add_local (spftree, |
isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, | spftree->area->oldmetric ? |
adj->sysid, adj, | VTYPE_NONPSEUDO_IS : |
circuit->te_metric[level - 1], family); | VTYPE_NONPSEUDO_TE_IS, |
| adj->sysid, adj, |
| circuit->te_metric[level - 1], |
| family, parent); |
memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); |
memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); |
LSP_PSEUDO_ID (lsp_id) = 0; |
LSP_PSEUDO_ID (lsp_id) = 0; |
LSP_FRAGMENT (lsp_id) = 0; |
LSP_FRAGMENT (lsp_id) = 0; |
lsp = lsp_search (lsp_id, area->lspdb[level - 1]); | lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]); |
if (!lsp) | if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) |
zlog_warn ("No lsp found for IS adjacency"); | zlog_warn ("ISIS-Spf: No LSP %s found for IS adjacency " |
/* else { | "L%d on %s (ID %u)", |
isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family); | rawlspid_print (lsp_id), level, |
} */ | circuit->interface->name, circuit->circuit_id); |
break; |
break; |
case ISIS_SYSTYPE_UNKNOWN: |
case ISIS_SYSTYPE_UNKNOWN: |
default: |
default: |
zlog_warn ("isis_spf_preload_tent unknow adj type"); |
zlog_warn ("isis_spf_preload_tent unknow adj type"); |
} |
} |
anode = listnextnode (anode); |
|
} |
} |
list_delete (adj_list); |
list_delete (adj_list); |
/* |
/* |
Line 878 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 1045 isis_spf_preload_tent (struct isis_spftree *spftree,
|
memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); |
memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); |
else |
else |
memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); |
memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); |
lsp = lsp_search (lsp_id, area->lspdb[level - 1]); | /* 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)", |
| level, circuit->interface->name, circuit->circuit_id); |
| continue; |
| } |
adj = isis_adj_lookup (lsp_id, adjdb); |
adj = isis_adj_lookup (lsp_id, adjdb); |
/* if no adj, we are the dis or error */ |
/* if no adj, we are the dis or error */ |
if (!adj && !circuit->u.bc.is_dr[level - 1]) |
if (!adj && !circuit->u.bc.is_dr[level - 1]) |
{ |
{ |
zlog_warn ("ISIS-Spf: No adjacency found for DR"); | zlog_warn ("ISIS-Spf: No adjacency found from root " |
| "to L%d DR %s on %s (ID %d)", |
| level, rawlspid_print (lsp_id), |
| circuit->interface->name, circuit->circuit_id); |
| continue; |
} |
} |
|
lsp = lsp_search (lsp_id, spftree->area->lspdb[level - 1]); |
if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) |
if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) |
{ |
{ |
zlog_warn ("ISIS-Spf: No lsp found for DR"); | zlog_warn ("ISIS-Spf: No lsp (%p) found from root " |
| "to L%d DR %s on %s (ID %d)", |
| lsp, level, rawlspid_print (lsp_id), |
| circuit->interface->name, circuit->circuit_id); |
| continue; |
} |
} |
else | isis_spf_process_pseudo_lsp (spftree, lsp, |
{ | circuit->te_metric[level - 1], 0, |
isis_spf_process_pseudo_lsp (spftree, lsp, | family, root_sysid, parent); |
circuit->te_metric[level - 1], 0, family); | |
| |
} | |
} |
} |
else if (circuit->circ_type == CIRCUIT_T_P2P) |
else if (circuit->circ_type == CIRCUIT_T_P2P) |
{ |
{ |
Line 905 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 1085 isis_spf_preload_tent (struct isis_spftree *spftree,
|
{ |
{ |
case ISIS_SYSTYPE_ES: |
case ISIS_SYSTYPE_ES: |
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, |
isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, |
circuit->te_metric[level - 1], family); | circuit->te_metric[level - 1], family, |
| parent); |
break; |
break; |
case ISIS_SYSTYPE_IS: |
case ISIS_SYSTYPE_IS: |
case ISIS_SYSTYPE_L1_IS: |
case ISIS_SYSTYPE_L1_IS: |
case ISIS_SYSTYPE_L2_IS: |
case ISIS_SYSTYPE_L2_IS: |
if (speaks (&adj->nlpids, family)) |
if (speaks (&adj->nlpids, family)) |
isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid, | isis_spf_add_local (spftree, |
| spftree->area->oldmetric ? |
| VTYPE_NONPSEUDO_IS : |
| VTYPE_NONPSEUDO_TE_IS, |
| adj->sysid, |
adj, circuit->te_metric[level - 1], |
adj, circuit->te_metric[level - 1], |
family); | family, parent); |
break; |
break; |
case ISIS_SYSTYPE_UNKNOWN: |
case ISIS_SYSTYPE_UNKNOWN: |
default: |
default: |
zlog_warn ("isis_spf_preload_tent unknow adj type"); | zlog_warn ("isis_spf_preload_tent unknown adj type"); |
break; |
break; |
} |
} |
} |
} |
|
else if (circuit->circ_type == CIRCUIT_T_LOOPBACK) |
|
{ |
|
continue; |
|
} |
else |
else |
{ |
{ |
zlog_warn ("isis_spf_preload_tent unsupported media"); |
zlog_warn ("isis_spf_preload_tent unsupported media"); |
retval = ISIS_WARNING; |
retval = ISIS_WARNING; |
} |
} |
|
|
} |
} |
|
|
return retval; |
return retval; |
Line 938 isis_spf_preload_tent (struct isis_spftree *spftree,
|
Line 1126 isis_spf_preload_tent (struct isis_spftree *spftree,
|
*/ |
*/ |
static void |
static void |
add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex, |
add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex, |
struct isis_area *area, int level) | int level) |
{ |
{ |
#ifdef EXTREME_DEBUG |
|
u_char buff[BUFSIZ]; |
u_char buff[BUFSIZ]; |
#endif /* EXTREME_DEBUG */ | |
| if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) |
| return; |
listnode_add (spftree->paths, vertex); |
listnode_add (spftree->paths, vertex); |
|
|
#ifdef EXTREME_DEBUG |
#ifdef EXTREME_DEBUG |
zlog_debug ("ISIS-Spf: added %s %s depth %d dist %d to PATHS", | zlog_debug ("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS", |
| print_sys_hostname (vertex->N.id), |
vtype2string (vertex->type), vid2string (vertex, buff), |
vtype2string (vertex->type), vid2string (vertex, buff), |
vertex->depth, vertex->d_N); |
vertex->depth, vertex->d_N); |
#endif /* EXTREME_DEBUG */ |
#endif /* EXTREME_DEBUG */ |
|
|
if (vertex->type > VTYPE_ES) |
if (vertex->type > VTYPE_ES) |
{ |
{ |
if (listcount (vertex->Adj_N) > 0) |
if (listcount (vertex->Adj_N) > 0) |
isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N, |
isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N, |
vertex->depth, vertex->Adj_N, area, level); | vertex->depth, vertex->Adj_N, spftree->area, level); |
else if (isis->debugs & DEBUG_SPF_EVENTS) |
else if (isis->debugs & DEBUG_SPF_EVENTS) |
zlog_debug ("ISIS-Spf: no adjacencies do not install route"); | zlog_debug ("ISIS-Spf: no adjacencies do not install route for " |
| "%s depth %d dist %d", vid2string (vertex, buff), |
| vertex->depth, vertex->d_N); |
} |
} |
|
|
return; |
return; |
Line 969 init_spt (struct isis_spftree *spftree)
|
Line 1162 init_spt (struct isis_spftree *spftree)
|
list_delete_all_node (spftree->tents); |
list_delete_all_node (spftree->tents); |
list_delete_all_node (spftree->paths); |
list_delete_all_node (spftree->paths); |
spftree->tents->del = spftree->paths->del = NULL; |
spftree->tents->del = spftree->paths->del = NULL; |
|
|
return; |
return; |
} |
} |
|
|
static int |
static int |
isis_run_spf (struct isis_area *area, int level, int family) | isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid) |
{ |
{ |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
struct listnode *node; |
struct listnode *node; |
struct isis_vertex *vertex; |
struct isis_vertex *vertex; |
|
struct isis_vertex *root_vertex; |
struct isis_spftree *spftree = NULL; |
struct isis_spftree *spftree = NULL; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
struct route_table *table = NULL; |
struct route_table *table = NULL; |
struct route_node *rode; | struct timespec time_now; |
struct isis_route_info *rinfo; | unsigned long long start_time, end_time; |
|
|
|
/* Get time that can't roll backwards. */ |
|
clock_gettime(CLOCK_MONOTONIC, &time_now); |
|
start_time = time_now.tv_sec; |
|
start_time = (start_time * 1000000) + (time_now.tv_nsec / 1000); |
|
|
if (family == AF_INET) |
if (family == AF_INET) |
spftree = area->spftree[level - 1]; |
spftree = area->spftree[level - 1]; |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
else if (family == AF_INET6) |
else if (family == AF_INET6) |
spftree = area->spftree6[level - 1]; |
spftree = area->spftree6[level - 1]; |
#endif |
#endif |
|
|
assert (spftree); |
assert (spftree); |
|
assert (sysid); |
|
|
/* Make all routes in current route table inactive. */ |
/* Make all routes in current route table inactive. */ |
if (family == AF_INET) |
if (family == AF_INET) |
Line 1003 isis_run_spf (struct isis_area *area, int level, int f
|
Line 1201 isis_run_spf (struct isis_area *area, int level, int f
|
table = area->route_table6[level - 1]; |
table = area->route_table6[level - 1]; |
#endif |
#endif |
|
|
for (rode = route_top (table); rode; rode = route_next (rode)) | isis_route_invalidate_table (area, table); |
{ | |
if (rode->info == NULL) | |
continue; | |
rinfo = rode->info; | |
|
|
UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); |
|
} |
|
|
|
/* |
/* |
* C.2.5 Step 0 |
* C.2.5 Step 0 |
*/ |
*/ |
init_spt (spftree); |
init_spt (spftree); |
/* a) */ |
/* a) */ |
isis_spf_add_self (spftree, area, level); | root_vertex = isis_spf_add_root (spftree, level, sysid); |
/* b) */ |
/* b) */ |
retval = isis_spf_preload_tent (spftree, area, level, family); | retval = isis_spf_preload_tent (spftree, level, family, sysid, root_vertex); |
| if (retval != ISIS_OK) |
| { |
| zlog_warn ("ISIS-Spf: failed to load TENT SPF-root:%s", print_sys_hostname(sysid)); |
| goto out; |
| } |
|
|
/* |
/* |
* C.2.7 Step 2 |
* C.2.7 Step 2 |
*/ |
*/ |
if (listcount (spftree->tents) == 0) |
if (listcount (spftree->tents) == 0) |
{ |
{ |
zlog_warn ("ISIS-Spf: TENT is empty"); | zlog_warn ("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid)); |
goto out; |
goto out; |
} |
} |
|
|
Line 1034 isis_run_spf (struct isis_area *area, int level, int f
|
Line 1230 isis_run_spf (struct isis_area *area, int level, int f
|
{ |
{ |
node = listhead (spftree->tents); |
node = listhead (spftree->tents); |
vertex = listgetdata (node); |
vertex = listgetdata (node); |
/* Remove from tent list */ | |
| #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 */ |
list_delete_node (spftree->tents, node); |
list_delete_node (spftree->tents, node); |
if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) | add_to_paths (spftree, vertex, level); |
continue; | switch (vertex->type) |
add_to_paths (spftree, vertex, area, level); | { |
if (vertex->type == VTYPE_PSEUDO_IS || | case VTYPE_PSEUDO_IS: |
vertex->type == VTYPE_NONPSEUDO_IS) | case VTYPE_NONPSEUDO_IS: |
{ | case VTYPE_PSEUDO_TE_IS: |
| case VTYPE_NONPSEUDO_TE_IS: |
memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); |
memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); |
LSP_FRAGMENT (lsp_id) = 0; |
LSP_FRAGMENT (lsp_id) = 0; |
lsp = lsp_search (lsp_id, area->lspdb[level - 1]); |
lsp = lsp_search (lsp_id, area->lspdb[level - 1]); |
if (lsp) | if (lsp && lsp->lsp_header->rem_lifetime != 0) |
{ |
{ |
if (LSP_PSEUDO_ID (lsp_id)) |
if (LSP_PSEUDO_ID (lsp_id)) |
{ |
{ |
isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, |
isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, |
vertex->depth, family); | vertex->depth, family, sysid, |
| vertex); |
} |
} |
else |
else |
{ |
{ |
isis_spf_process_lsp (spftree, lsp, vertex->d_N, |
isis_spf_process_lsp (spftree, lsp, vertex->d_N, |
vertex->depth, family); | vertex->depth, family, sysid, vertex); |
} |
} |
} |
} |
else |
else |
Line 1064 isis_run_spf (struct isis_area *area, int level, int f
|
Line 1268 isis_run_spf (struct isis_area *area, int level, int f
|
zlog_warn ("ISIS-Spf: No LSP found for %s", |
zlog_warn ("ISIS-Spf: No LSP found for %s", |
rawlspid_print (lsp_id)); |
rawlspid_print (lsp_id)); |
} |
} |
|
break; |
|
default:; |
} |
} |
} |
} |
|
|
out: |
out: |
thread_add_event (master, isis_route_validate, area, 0); | isis_route_validate (area); |
spftree->lastrun = time (NULL); | |
spftree->pending = 0; |
spftree->pending = 0; |
|
spftree->runcount++; |
|
spftree->last_run_timestamp = time (NULL); |
|
clock_gettime(CLOCK_MONOTONIC, &time_now); |
|
end_time = time_now.tv_sec; |
|
end_time = (end_time * 1000000) + (time_now.tv_nsec / 1000); |
|
spftree->last_run_duration = end_time - start_time; |
|
|
|
|
return retval; |
return retval; |
} |
} |
|
|
Line 1085 isis_run_spf_l1 (struct thread *thread)
|
Line 1297 isis_run_spf_l1 (struct thread *thread)
|
assert (area); |
assert (area); |
|
|
area->spftree[0]->t_spf = NULL; |
area->spftree[0]->t_spf = NULL; |
|
area->spftree[0]->pending = 0; |
|
|
if (!(area->is_type & IS_LEVEL_1)) |
if (!(area->is_type & IS_LEVEL_1)) |
{ |
{ |
Line 1098 isis_run_spf_l1 (struct thread *thread)
|
Line 1311 isis_run_spf_l1 (struct thread *thread)
|
zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag); |
zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag); |
|
|
if (area->ip_circuits) |
if (area->ip_circuits) |
retval = isis_run_spf (area, 1, AF_INET); | retval = isis_run_spf (area, 1, AF_INET, isis->sysid); |
|
|
THREAD_TIMER_ON (master, area->spftree[0]->t_spf, isis_run_spf_l1, area, |
|
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); |
|
|
|
return retval; |
return retval; |
} |
} |
|
|
Line 1116 isis_run_spf_l2 (struct thread *thread)
|
Line 1326 isis_run_spf_l2 (struct thread *thread)
|
assert (area); |
assert (area); |
|
|
area->spftree[1]->t_spf = NULL; |
area->spftree[1]->t_spf = NULL; |
|
area->spftree[1]->pending = 0; |
|
|
if (!(area->is_type & IS_LEVEL_2)) |
if (!(area->is_type & IS_LEVEL_2)) |
{ |
{ |
Line 1128 isis_run_spf_l2 (struct thread *thread)
|
Line 1339 isis_run_spf_l2 (struct thread *thread)
|
zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag); |
zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag); |
|
|
if (area->ip_circuits) |
if (area->ip_circuits) |
retval = isis_run_spf (area, 2, AF_INET); | retval = isis_run_spf (area, 2, AF_INET, isis->sysid); |
|
|
THREAD_TIMER_ON (master, area->spftree[1]->t_spf, isis_run_spf_l2, area, |
|
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); |
|
|
|
return retval; |
return retval; |
} |
} |
|
|
int |
int |
isis_spf_schedule (struct isis_area *area, int level) |
isis_spf_schedule (struct isis_area *area, int level) |
{ |
{ |
int retval = ISIS_OK; |
|
struct isis_spftree *spftree = area->spftree[level - 1]; |
struct isis_spftree *spftree = area->spftree[level - 1]; |
time_t diff, now = time (NULL); | time_t now = time (NULL); |
| int diff = now - spftree->last_run_timestamp; |
|
|
if (spftree->pending) | assert (diff >= 0); |
return retval; | assert (area->is_type & level); |
|
|
diff = now - spftree->lastrun; | 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); |
|
|
/* FIXME: let's wait a minute before doing the SPF */ | if (spftree->pending) |
if (now - isis->uptime < 60 || isis->uptime == 0) | return ISIS_OK; |
{ | |
if (level == 1) | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, 60); | |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, 60); | |
|
|
spftree->pending = 1; |
|
return retval; |
|
} |
|
|
|
THREAD_TIMER_OFF (spftree->t_spf); |
THREAD_TIMER_OFF (spftree->t_spf); |
|
|
if (diff < MINIMUM_SPF_INTERVAL) | /* wait configured min_spf_interval before doing the SPF */ |
{ | if (diff >= area->min_spf_interval[level-1]) |
if (level == 1) | return isis_run_spf (area, level, AF_INET, isis->sysid); |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, | |
MINIMUM_SPF_INTERVAL - diff); | |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, | |
MINIMUM_SPF_INTERVAL - diff); | |
|
|
spftree->pending = 1; | if (level == 1) |
} | THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, |
| area->min_spf_interval[0] - diff); |
else |
else |
{ | THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, |
spftree->pending = 0; | area->min_spf_interval[1] - diff); |
retval = isis_run_spf (area, level, AF_INET); | |
if (level == 1) | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l1, area, | |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); | |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf_l2, area, | |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); | |
} | |
|
|
return retval; | if (isis->debugs & DEBUG_SPF_EVENTS) |
| zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now", |
| area->area_tag, level, area->min_spf_interval[level-1] - diff); |
| |
| spftree->pending = 1; |
| |
| return ISIS_OK; |
} |
} |
|
|
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
Line 1199 isis_run_spf6_l1 (struct thread *thread)
|
Line 1394 isis_run_spf6_l1 (struct thread *thread)
|
assert (area); |
assert (area); |
|
|
area->spftree6[0]->t_spf = NULL; |
area->spftree6[0]->t_spf = NULL; |
|
area->spftree6[0]->pending = 0; |
|
|
if (!(area->is_type & IS_LEVEL_1)) |
if (!(area->is_type & IS_LEVEL_1)) |
{ |
{ |
if (isis->debugs & DEBUG_SPF_EVENTS) |
if (isis->debugs & DEBUG_SPF_EVENTS) |
zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag); | zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag); |
return ISIS_WARNING; |
return ISIS_WARNING; |
} |
} |
|
|
Line 1211 isis_run_spf6_l1 (struct thread *thread)
|
Line 1407 isis_run_spf6_l1 (struct thread *thread)
|
zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag); |
zlog_debug ("ISIS-Spf (%s) L1 SPF needed, periodic SPF", area->area_tag); |
|
|
if (area->ipv6_circuits) |
if (area->ipv6_circuits) |
retval = isis_run_spf (area, 1, AF_INET6); | retval = isis_run_spf (area, 1, AF_INET6, isis->sysid); |
|
|
THREAD_TIMER_ON (master, area->spftree6[0]->t_spf, isis_run_spf6_l1, area, |
|
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); |
|
|
|
return retval; |
return retval; |
} |
} |
|
|
Line 1229 isis_run_spf6_l2 (struct thread *thread)
|
Line 1422 isis_run_spf6_l2 (struct thread *thread)
|
assert (area); |
assert (area); |
|
|
area->spftree6[1]->t_spf = NULL; |
area->spftree6[1]->t_spf = NULL; |
|
area->spftree6[1]->pending = 0; |
|
|
if (!(area->is_type & IS_LEVEL_2)) |
if (!(area->is_type & IS_LEVEL_2)) |
{ |
{ |
Line 1241 isis_run_spf6_l2 (struct thread *thread)
|
Line 1435 isis_run_spf6_l2 (struct thread *thread)
|
zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag); |
zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag); |
|
|
if (area->ipv6_circuits) |
if (area->ipv6_circuits) |
retval = isis_run_spf (area, 2, AF_INET6); | retval = isis_run_spf (area, 2, AF_INET6, isis->sysid); |
|
|
THREAD_TIMER_ON (master, area->spftree6[1]->t_spf, isis_run_spf6_l2, area, |
|
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); |
|
|
|
return retval; |
return retval; |
} |
} |
|
|
Line 1254 isis_spf_schedule6 (struct isis_area *area, int level)
|
Line 1445 isis_spf_schedule6 (struct isis_area *area, int level)
|
{ |
{ |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
struct isis_spftree *spftree = area->spftree6[level - 1]; |
struct isis_spftree *spftree = area->spftree6[level - 1]; |
time_t diff, now = time (NULL); | time_t now = time (NULL); |
| time_t diff = now - spftree->last_run_timestamp; |
|
|
if (spftree->pending) | assert (diff >= 0); |
return retval; | assert (area->is_type & level); |
|
|
diff = now - spftree->lastrun; | 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); |
|
|
/* FIXME: let's wait a minute before doing the SPF */ | if (spftree->pending) |
if (now - isis->uptime < 60 || isis->uptime == 0) | return ISIS_OK; |
{ | |
if (level == 1) | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, 60); | |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, 60); | |
|
|
spftree->pending = 1; |
|
return retval; |
|
} |
|
|
|
THREAD_TIMER_OFF (spftree->t_spf); |
THREAD_TIMER_OFF (spftree->t_spf); |
|
|
if (diff < MINIMUM_SPF_INTERVAL) | /* wait configured min_spf_interval before doing the SPF */ |
{ | if (diff >= area->min_spf_interval[level-1]) |
if (level == 1) | return isis_run_spf (area, level, AF_INET6, isis->sysid); |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, | |
MINIMUM_SPF_INTERVAL - diff); | |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, | |
MINIMUM_SPF_INTERVAL - diff); | |
|
|
spftree->pending = 1; | if (level == 1) |
} | THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, |
| area->min_spf_interval[0] - diff); |
else |
else |
{ | THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, |
spftree->pending = 0; | area->min_spf_interval[1] - diff); |
retval = isis_run_spf (area, level, AF_INET6); | |
|
|
if (level == 1) | if (isis->debugs & DEBUG_SPF_EVENTS) |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l1, area, | zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now", |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); | area->area_tag, level, area->min_spf_interval[level-1] - diff); |
else | |
THREAD_TIMER_ON (master, spftree->t_spf, isis_run_spf6_l2, area, | |
isis_jitter (PERIODIC_SPF_INTERVAL, 10)); | |
} | |
|
|
|
spftree->pending = 1; |
|
|
return retval; |
return retval; |
} |
} |
#endif |
#endif |
|
|
static void |
static void |
isis_print_paths (struct vty *vty, struct list *paths) | isis_print_paths (struct vty *vty, struct list *paths, u_char *root_sysid) |
{ |
{ |
struct listnode *node; |
struct listnode *node; |
|
struct listnode *anode; |
struct isis_vertex *vertex; |
struct isis_vertex *vertex; |
struct isis_dynhn *dyn, *nh_dyn = NULL; |
|
struct isis_adjacency *adj; |
struct isis_adjacency *adj; |
#if 0 |
|
u_char buff[255]; |
u_char buff[255]; |
#endif /* 0 */ |
|
|
|
vty_out (vty, "System Id Metric Next-Hop" | vty_out (vty, "Vertex Type Metric " |
" Interface SNPA%s", VTY_NEWLINE); | "Next-Hop Interface Parent%s", VTY_NEWLINE); |
|
|
for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) | for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) { |
{ | if (memcmp (vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) { |
if (vertex->type != VTYPE_NONPSEUDO_IS) | vty_out (vty, "%-20s %-12s %-6s", print_sys_hostname (root_sysid), |
continue; | "", ""); |
if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0) | vty_out (vty, "%-30s", ""); |
{ | } else { |
vty_out (vty, "%s --%s", host.name?host.name:"", | int rows = 0; |
VTY_NEWLINE); | vty_out (vty, "%-20s %-12s %-6u ", vid2string (vertex, buff), |
} | vtype2string (vertex->type), vertex->d_N); |
else | for (ALL_LIST_ELEMENTS_RO (vertex->Adj_N, anode, adj)) { |
{ | if (adj) { |
dyn = dynhn_find_by_id ((u_char *) vertex->N.id); | if (rows) { |
adj = listgetdata (listhead (vertex->Adj_N)); | vty_out (vty, "%s", VTY_NEWLINE); |
if (adj) | vty_out (vty, "%-20s %-12s %-6s ", "", "", ""); |
{ | |
nh_dyn = dynhn_find_by_id (adj->sysid); | |
vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s", | |
(dyn != NULL) ? dyn->name.name : | |
(const u_char *)rawlspid_print ((u_char *) vertex->N.id), | |
vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name : | |
(const u_char *)rawlspid_print (adj->sysid), | |
adj->circuit->interface->name, | |
snpa_print (adj->snpa), VTY_NEWLINE); | |
} |
} |
else | vty_out (vty, "%-20s %-9s ", |
{ | print_sys_hostname (adj->sysid), |
vty_out (vty, "%s %u %s", dyn ? dyn->name.name : | adj->circuit->interface->name); |
(const u_char *) rawlspid_print (vertex->N.id), | ++rows; |
vertex->d_N, VTY_NEWLINE); | } |
} | |
} |
} |
|
if (rows == 0) |
|
vty_out (vty, "%-30s ", ""); |
|
} |
|
|
|
/* 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)", |
|
vid2string (pvertex, buff), pvertex->type); |
|
++rows; |
|
} |
|
} else { |
|
vty_out (vty, " NULL "); |
|
} |
|
|
#if 0 |
#if 0 |
vty_out (vty, "%s %s %u %s", vtype2string (vertex->type), | if (listcount (vertex->children) > 0) { |
vid2string (vertex, buff), vertex->d_N, VTY_NEWLINE); | struct listnode *cnode; |
| struct isis_vertex *cvertex; |
| for (ALL_LIST_ELEMENTS_RO (vertex->children, cnode, cvertex)) { |
| vty_out (vty, "%s", VTY_NEWLINE); |
| vty_out (vty, "%-72s", ""); |
| vty_out (vty, "%s(%d) ", |
| vid2string (cvertex, buff), cvertex->type); |
| } |
| } |
#endif |
#endif |
|
vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
} |
} |
|
|
Line 1381 DEFUN (show_isis_topology,
|
Line 1578 DEFUN (show_isis_topology,
|
{ |
{ |
vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s", |
vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s", |
level + 1, VTY_NEWLINE); |
level + 1, VTY_NEWLINE); |
isis_print_paths (vty, area->spftree[level]->paths); | isis_print_paths (vty, area->spftree[level]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
if (area->ipv6_circuits > 0 && area->spftree6[level] |
if (area->ipv6_circuits > 0 && area->spftree6[level] |
Line 1390 DEFUN (show_isis_topology,
|
Line 1588 DEFUN (show_isis_topology,
|
vty_out (vty, |
vty_out (vty, |
"IS-IS paths to level-%d routers that speak IPv6%s", |
"IS-IS paths to level-%d routers that speak IPv6%s", |
level + 1, VTY_NEWLINE); |
level + 1, VTY_NEWLINE); |
isis_print_paths (vty, area->spftree6[level]->paths); | isis_print_paths (vty, area->spftree6[level]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
} |
} |
|
|
|
vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
|
|
return CMD_SUCCESS; |
return CMD_SUCCESS; |
Line 1423 DEFUN (show_isis_topology_l1,
|
Line 1624 DEFUN (show_isis_topology_l1,
|
{ |
{ |
vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s", |
vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s", |
VTY_NEWLINE); |
VTY_NEWLINE); |
isis_print_paths (vty, area->spftree[0]->paths); | isis_print_paths (vty, area->spftree[0]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
if (area->ipv6_circuits > 0 && area->spftree6[0] |
if (area->ipv6_circuits > 0 && area->spftree6[0] |
Line 1431 DEFUN (show_isis_topology_l1,
|
Line 1633 DEFUN (show_isis_topology_l1,
|
{ |
{ |
vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s", |
vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s", |
VTY_NEWLINE); |
VTY_NEWLINE); |
isis_print_paths (vty, area->spftree6[0]->paths); | isis_print_paths (vty, area->spftree6[0]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
|
|
return CMD_SUCCESS; |
return CMD_SUCCESS; |
Line 1463 DEFUN (show_isis_topology_l2,
|
Line 1667 DEFUN (show_isis_topology_l2,
|
{ |
{ |
vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s", |
vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s", |
VTY_NEWLINE); |
VTY_NEWLINE); |
isis_print_paths (vty, area->spftree[1]->paths); | isis_print_paths (vty, area->spftree[1]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
if (area->ipv6_circuits > 0 && area->spftree6[1] |
if (area->ipv6_circuits > 0 && area->spftree6[1] |
Line 1471 DEFUN (show_isis_topology_l2,
|
Line 1676 DEFUN (show_isis_topology_l2,
|
{ |
{ |
vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s", |
vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s", |
VTY_NEWLINE); |
VTY_NEWLINE); |
isis_print_paths (vty, area->spftree6[1]->paths); | isis_print_paths (vty, area->spftree6[1]->paths, isis->sysid); |
| vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
vty_out (vty, "%s", VTY_NEWLINE); |
} |
} |
|
|
return CMD_SUCCESS; |
return CMD_SUCCESS; |