|
version 1.1.1.1, 2012/02/21 17:26:11
|
version 1.1.1.3, 2013/07/21 23:54:38
|
|
Line 36
|
Line 36
|
| #include "isisd/include-netbsd/iso.h" |
#include "isisd/include-netbsd/iso.h" |
| #include "isisd/isis_constants.h" |
#include "isisd/isis_constants.h" |
| #include "isisd/isis_common.h" |
#include "isisd/isis_common.h" |
| |
#include "isisd/isis_flags.h" |
| #include "isisd/isisd.h" |
#include "isisd/isisd.h" |
| #include "isisd/isis_circuit.h" |
#include "isisd/isis_circuit.h" |
| #include "isisd/isis_adjacency.h" |
#include "isisd/isis_adjacency.h" |
|
Line 43
|
Line 44
|
| #include "isisd/isis_dr.h" |
#include "isisd/isis_dr.h" |
| #include "isisd/isis_dynhn.h" |
#include "isisd/isis_dynhn.h" |
| #include "isisd/isis_pdu.h" |
#include "isisd/isis_pdu.h" |
| |
#include "isisd/isis_tlv.h" |
| |
#include "isisd/isis_lsp.h" |
| |
#include "isisd/isis_spf.h" |
| |
#include "isisd/isis_events.h" |
| |
|
| extern struct isis *isis; |
extern struct isis *isis; |
| |
|
|
Line 73 isis_new_adj (u_char * id, u_char * snpa, int level,
|
Line 78 isis_new_adj (u_char * id, u_char * snpa, int level,
|
| } |
} |
| |
|
| if (snpa) { |
if (snpa) { |
| memcpy (adj->snpa, snpa, 6); | memcpy (adj->snpa, snpa, ETH_ALEN); |
| } else { |
} else { |
| memset (adj->snpa, ' ', 6); | memset (adj->snpa, ' ', ETH_ALEN); |
| } |
} |
| |
|
| adj->circuit = circuit; |
adj->circuit = circuit; |
|
Line 125 isis_adj_lookup_snpa (u_char * ssnpa, struct list *adj
|
Line 130 isis_adj_lookup_snpa (u_char * ssnpa, struct list *adj
|
| } |
} |
| |
|
| void |
void |
| isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb) | isis_delete_adj (void *arg) |
| { |
{ |
| |
struct isis_adjacency *adj = arg; |
| |
|
| if (!adj) |
if (!adj) |
| return; |
return; |
| /* When we recieve a NULL list, we will know its p2p. */ |
|
| if (adjdb) |
|
| listnode_delete (adjdb, adj); |
|
| |
|
| THREAD_OFF (adj->t_expire); | THREAD_TIMER_OFF (adj->t_expire); |
| |
|
| |
/* remove from SPF trees */ |
| |
spftree_area_adj_del (adj->circuit->area, adj); |
| |
|
| |
if (adj->area_addrs) |
| |
list_delete (adj->area_addrs); |
| if (adj->ipv4_addrs) |
if (adj->ipv4_addrs) |
| list_delete (adj->ipv4_addrs); |
list_delete (adj->ipv4_addrs); |
| #ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
| if (adj->ipv6_addrs) |
if (adj->ipv6_addrs) |
| list_delete (adj->ipv6_addrs); |
list_delete (adj->ipv6_addrs); |
| #endif |
#endif |
| | |
| XFREE (MTYPE_ISIS_ADJACENCY, adj); |
XFREE (MTYPE_ISIS_ADJACENCY, adj); |
| return; |
return; |
| } |
} |
| |
|
| |
static const char * |
| |
adj_state2string (int state) |
| |
{ |
| |
|
| |
switch (state) |
| |
{ |
| |
case ISIS_ADJ_INITIALIZING: |
| |
return "Initializing"; |
| |
case ISIS_ADJ_UP: |
| |
return "Up"; |
| |
case ISIS_ADJ_DOWN: |
| |
return "Down"; |
| |
default: |
| |
return "Unknown"; |
| |
} |
| |
|
| |
return NULL; /* not reached */ |
| |
} |
| |
|
| void |
void |
| isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, | isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state, |
| const char *reason) |
const char *reason) |
| { |
{ |
| int old_state; |
int old_state; |
| int level = adj->level; | int level; |
| struct isis_circuit *circuit; |
struct isis_circuit *circuit; |
| |
|
| old_state = adj->adj_state; |
old_state = adj->adj_state; |
| adj->adj_state = state; | adj->adj_state = new_state; |
| |
|
| circuit = adj->circuit; |
circuit = adj->circuit; |
| |
|
|
Line 163 isis_adj_state_change (struct isis_adjacency *adj, enu
|
Line 191 isis_adj_state_change (struct isis_adjacency *adj, enu
|
| { |
{ |
| zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", |
zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", |
| circuit->area->area_tag, |
circuit->area->area_tag, |
| old_state, state, reason ? reason : "unspecified"); | old_state, new_state, reason ? reason : "unspecified"); |
| } |
} |
| |
|
| |
if (circuit->area->log_adj_changes) |
| |
{ |
| |
const char *adj_name; |
| |
struct isis_dynhn *dyn; |
| |
|
| |
dyn = dynhn_find_by_id (adj->sysid); |
| |
if (dyn) |
| |
adj_name = (const char *)dyn->name.name; |
| |
else |
| |
adj_name = adj->sysid ? sysid_print (adj->sysid) : "unknown"; |
| |
|
| |
zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", |
| |
adj_name, |
| |
adj->circuit->interface->name, |
| |
adj_state2string (old_state), |
| |
adj_state2string (new_state), |
| |
reason ? reason : "unspecified"); |
| |
} |
| |
|
| if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
| { |
{ |
| if (state == ISIS_ADJ_UP) | for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) |
| circuit->upadjcount[level - 1]++; | { |
| if (state == ISIS_ADJ_DOWN) | if ((adj->level & level) == 0) |
| { | continue; |
| isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]); | if (new_state == ISIS_ADJ_UP) |
| circuit->upadjcount[level - 1]--; | { |
| } | circuit->upadjcount[level - 1]++; |
| | isis_event_adjacency_state_change (adj, new_state); |
| | /* update counter & timers for debugging purposes */ |
| | adj->last_flap = time (NULL); |
| | adj->flaps++; |
| | } |
| | else if (new_state == ISIS_ADJ_DOWN) |
| | { |
| | listnode_delete (circuit->u.bc.adjdb[level - 1], adj); |
| | circuit->upadjcount[level - 1]--; |
| | if (circuit->upadjcount[level - 1] == 0) |
| | { |
| | /* Clean lsp_queue when no adj is up. */ |
| | if (circuit->lsp_queue) |
| | list_delete_all_node (circuit->lsp_queue); |
| | } |
| | isis_event_adjacency_state_change (adj, new_state); |
| | isis_delete_adj (adj); |
| | } |
| |
|
| list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); | if (circuit->u.bc.lan_neighs[level - 1]) |
| isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], | { |
| circuit->u.bc.lan_neighs[level - 1]); | list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); |
| | isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], |
| | circuit->u.bc.lan_neighs[level - 1]); |
| | } |
| | |
| | /* On adjacency state change send new pseudo LSP if we are the DR */ |
| | if (circuit->u.bc.is_dr[level - 1]) |
| | lsp_regenerate_schedule_pseudo (circuit, level); |
| | } |
| } |
} |
| else if (state == ISIS_ADJ_UP) | else if (circuit->circ_type == CIRCUIT_T_P2P) |
| { /* p2p interface */ | { |
| if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) | for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) |
| send_hello (circuit, 1); | { |
| | if ((adj->level & level) == 0) |
| | continue; |
| | if (new_state == ISIS_ADJ_UP) |
| | { |
| | circuit->upadjcount[level - 1]++; |
| | isis_event_adjacency_state_change (adj, new_state); |
| |
|
| /* update counter & timers for debugging purposes */ | if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) |
| adj->last_flap = time (NULL); | send_hello (circuit, level); |
| adj->flaps++; | |
| |
|
| /* 7.3.17 - going up on P2P -> send CSNP */ | /* update counter & timers for debugging purposes */ |
| /* FIXME: yup, I know its wrong... but i will do it! (for now) */ | adj->last_flap = time (NULL); |
| send_csnp (circuit, 1); | adj->flaps++; |
| send_csnp (circuit, 2); | |
| | /* 7.3.17 - going up on P2P -> send CSNP */ |
| | /* FIXME: yup, I know its wrong... but i will do it! (for now) */ |
| | send_csnp (circuit, level); |
| | } |
| | else if (new_state == ISIS_ADJ_DOWN) |
| | { |
| | if (adj->circuit->u.p2p.neighbor == adj) |
| | adj->circuit->u.p2p.neighbor = NULL; |
| | circuit->upadjcount[level - 1]--; |
| | if (circuit->upadjcount[level - 1] == 0) |
| | { |
| | /* Clean lsp_queue when no adj is up. */ |
| | if (circuit->lsp_queue) |
| | list_delete_all_node (circuit->lsp_queue); |
| | } |
| | isis_event_adjacency_state_change (adj, new_state); |
| | isis_delete_adj (adj); |
| | } |
| | } |
| } |
} |
| else if (state == ISIS_ADJ_DOWN) | |
| { /* p2p interface */ | |
| adj->circuit->u.p2p.neighbor = NULL; | |
| isis_delete_adj (adj, NULL); | |
| } | |
| return; |
return; |
| } |
} |
| |
|
|
Line 225 isis_adj_print (struct isis_adjacency *adj)
|
Line 318 isis_adj_print (struct isis_adjacency *adj)
|
| snpa_print (adj->snpa), adj->level, adj->hold_time); |
snpa_print (adj->snpa), adj->level, adj->hold_time); |
| if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
| { |
{ |
| zlog_debug ("IPv4 Addresses:"); | zlog_debug ("IPv4 Address(es):"); |
| |
|
| for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) |
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) |
| zlog_debug ("%s", inet_ntoa (*ipv4_addr)); |
zlog_debug ("%s", inet_ntoa (*ipv4_addr)); |
|
Line 234 isis_adj_print (struct isis_adjacency *adj)
|
Line 327 isis_adj_print (struct isis_adjacency *adj)
|
| #ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
| if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
| { |
{ |
| zlog_debug ("IPv6 Addresses:"); | zlog_debug ("IPv6 Address(es):"); |
| for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
| { |
{ |
| inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
|
Line 251 int
|
Line 344 int
|
| isis_adj_expire (struct thread *thread) |
isis_adj_expire (struct thread *thread) |
| { |
{ |
| struct isis_adjacency *adj; |
struct isis_adjacency *adj; |
| int level; |
|
| |
|
| /* |
/* |
| * Get the adjacency |
* Get the adjacency |
| */ |
*/ |
| adj = THREAD_ARG (thread); |
adj = THREAD_ARG (thread); |
| assert (adj); |
assert (adj); |
| level = adj->level; |
|
| adj->t_expire = NULL; |
adj->t_expire = NULL; |
| |
|
| /* trigger the adj expire event */ |
/* trigger the adj expire event */ |
|
Line 267 isis_adj_expire (struct thread *thread)
|
Line 358 isis_adj_expire (struct thread *thread)
|
| return 0; |
return 0; |
| } |
} |
| |
|
| static const char * |
|
| adj_state2string (int state) |
|
| { |
|
| |
|
| switch (state) |
|
| { |
|
| case ISIS_ADJ_INITIALIZING: |
|
| return "Initializing"; |
|
| case ISIS_ADJ_UP: |
|
| return "Up"; |
|
| case ISIS_ADJ_DOWN: |
|
| return "Down"; |
|
| default: |
|
| return "Unknown"; |
|
| } |
|
| |
|
| return NULL; /* not reached */ |
|
| } |
|
| |
|
| /* |
/* |
| * show clns/isis neighbor (detail) | * show isis neighbor [detail] |
| */ |
*/ |
| static void | void |
| isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail) | isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) |
| { |
{ |
| |
|
| #ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
| struct in6_addr *ipv6_addr; |
struct in6_addr *ipv6_addr; |
| u_char ip6[INET6_ADDRSTRLEN]; |
u_char ip6[INET6_ADDRSTRLEN]; |
|
Line 335 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
Line 406 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
| if (detail == ISIS_UI_LEVEL_DETAIL) |
if (detail == ISIS_UI_LEVEL_DETAIL) |
| { |
{ |
| level = adj->level; |
level = adj->level; |
| |
vty_out (vty, "%s", VTY_NEWLINE); |
| if (adj->circuit) |
if (adj->circuit) |
| vty_out (vty, "%s Interface: %s", VTY_NEWLINE, adj->circuit->interface->name); /* interface name */ | vty_out (vty, " Interface: %s", adj->circuit->interface->name); |
| else |
else |
| vty_out (vty, "NULL circuit!%s", VTY_NEWLINE); | vty_out (vty, " Interface: NULL circuit"); |
| vty_out (vty, ", Level: %u", adj->level); /* level */ |
vty_out (vty, ", Level: %u", adj->level); /* level */ |
| vty_out (vty, ", State: %s", adj_state2string (adj->adj_state)); |
vty_out (vty, ", State: %s", adj_state2string (adj->adj_state)); |
| now = time (NULL); |
now = time (NULL); |
|
Line 347 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
Line 419 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
| time2string (adj->last_upd + adj->hold_time - now)); |
time2string (adj->last_upd + adj->hold_time - now)); |
| else |
else |
| vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); |
vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); |
| vty_out (vty, "%s Adjacency flaps: %u", VTY_NEWLINE, adj->flaps); | vty_out (vty, "%s", VTY_NEWLINE); |
| | vty_out (vty, " Adjacency flaps: %u", adj->flaps); |
| vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap)); |
vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap)); |
| vty_out (vty, "%s Circuit type: %s", | vty_out (vty, "%s", VTY_NEWLINE); |
| VTY_NEWLINE, circuit_t2string (adj->circuit_t)); | vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t)); |
| vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); |
vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); |
| vty_out (vty, "%s SNPA: %s", VTY_NEWLINE, snpa_print (adj->snpa)); | vty_out (vty, "%s", VTY_NEWLINE); |
| dyn = dynhn_find_by_id (adj->lanid); | vty_out (vty, " SNPA: %s", snpa_print (adj->snpa)); |
| if (dyn) | if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) |
| vty_out (vty, ", LAN id: %s.%02x", | { |
| dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); | dyn = dynhn_find_by_id (adj->lanid); |
| else | if (dyn) |
| vty_out (vty, ", LAN id: %s.%02x", | vty_out (vty, ", LAN id: %s.%02x", |
| sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); | dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); |
| | else |
| | vty_out (vty, ", LAN id: %s.%02x", |
| | sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); |
| |
|
| vty_out (vty, "%s Priority: %u", | vty_out (vty, "%s", VTY_NEWLINE); |
| VTY_NEWLINE, adj->prio[adj->level - 1]); | vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]); |
| |
|
| vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s", | vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago", |
| isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. | isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. |
| dis), adj->dischanges[level - 1], | dis), adj->dischanges[level - 1], |
| time2string (now - | time2string (now - |
| (adj->dis_record[ISIS_LEVELS + level - 1]. | (adj->dis_record[ISIS_LEVELS + level - 1]. |
| last_dis_change)), VTY_NEWLINE); | last_dis_change))); |
| | } |
| | vty_out (vty, "%s", VTY_NEWLINE); |
| |
|
| |
if (adj->area_addrs && listcount (adj->area_addrs) > 0) |
| |
{ |
| |
struct area_addr *area_addr; |
| |
vty_out (vty, " Area Address(es):%s", VTY_NEWLINE); |
| |
for (ALL_LIST_ELEMENTS_RO (adj->area_addrs, node, area_addr)) |
| |
vty_out (vty, " %s%s", isonet_print (area_addr->area_addr, |
| |
area_addr->addr_len), VTY_NEWLINE); |
| |
} |
| if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
| { |
{ |
| vty_out (vty, " IPv4 Addresses:%s", VTY_NEWLINE); | vty_out (vty, " IPv4 Address(es):%s", VTY_NEWLINE); |
| for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr)) |
for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr)) |
| vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE); |
vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE); |
| } |
} |
| #ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
| if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
| { |
{ |
| vty_out (vty, " IPv6 Addresses:%s", VTY_NEWLINE); | vty_out (vty, " IPv6 Address(es):%s", VTY_NEWLINE); |
| for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
| { |
{ |
| inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
|
Line 391 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
Line 477 isis_adj_print_vty2 (struct isis_adjacency *adj, struc
|
| vty_out (vty, "%s", VTY_NEWLINE); |
vty_out (vty, "%s", VTY_NEWLINE); |
| } |
} |
| return; |
return; |
| } |
|
| |
|
| void |
|
| isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF); |
|
| } |
|
| |
|
| void |
|
| isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL); |
|
| } |
|
| |
|
| void |
|
| isis_adj_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE); |
|
| } |
|
| |
|
| void |
|
| isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF); |
|
| } |
|
| |
|
| void |
|
| isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL); |
|
| } |
|
| |
|
| void |
|
| isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty) |
|
| { |
|
| isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE); |
|
| } |
|
| |
|
| void |
|
| isis_adjdb_iterate (struct list *adjdb, void (*func) (struct isis_adjacency *, |
|
| void *), void *arg) |
|
| { |
|
| struct listnode *node, *nnode; |
|
| struct isis_adjacency *adj; |
|
| |
|
| for (ALL_LIST_ELEMENTS (adjdb, node, nnode, adj)) |
|
| (*func) (adj, arg); |
|
| } |
} |
| |
|
| void |
void |