forked from Mirror/frr
isisd: fix circuit state machine
isisd has a so-called circuit state machine that takes care about the interface state changes, such as initializing, down, up. When an interface was brought down by a link failure, the interface information was deleted and set to NULL. When the link was restored later, the interface was looked up by the old pointer, but since it was cleared, it was never found again, resulting in an interface never entering the up state again. Also, the program regularly crashed because of a deleted pointer in the same context which was later accessed without any further checking. Signed-off-by: Fritz Reichmann <fritz@reichmann.nl>
This commit is contained in:
parent
4c0cf00afc
commit
7fd6cd819f
|
@ -172,7 +172,7 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
|
|||
circuit->upadjcount[level - 1]++;
|
||||
if (state == ISIS_ADJ_DOWN)
|
||||
{
|
||||
isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]);
|
||||
listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj);
|
||||
circuit->upadjcount[level - 1]--;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ struct isis_p2p_info
|
|||
struct isis_circuit
|
||||
{
|
||||
int state;
|
||||
int connected;
|
||||
u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */
|
||||
struct isis_area *area; /* back pointer to the area */
|
||||
struct interface *interface; /* interface info from z */
|
||||
|
|
|
@ -112,6 +112,7 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
|||
isis_circuit_configure (circuit, (struct isis_area *) arg);
|
||||
isis_circuit_up (circuit);
|
||||
circuit->state = C_STATE_UP;
|
||||
circuit->connected = 1;
|
||||
isis_event_circuit_state_change (circuit, 1);
|
||||
listnode_delete (isis->init_circ_list, circuit);
|
||||
break;
|
||||
|
@ -136,9 +137,12 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
|||
zlog_warn ("circuit already enabled");
|
||||
break;
|
||||
case IF_UP_FROM_Z:
|
||||
if (!circuit->connected) {
|
||||
isis_circuit_if_add (circuit, (struct interface *) arg);
|
||||
isis_circuit_up (circuit);
|
||||
}
|
||||
circuit->state = C_STATE_UP;
|
||||
circuit->connected = 1;
|
||||
isis_event_circuit_state_change (circuit, 1);
|
||||
break;
|
||||
case ISIS_DISABLE:
|
||||
|
@ -167,7 +171,6 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg)
|
|||
isis_event_circuit_state_change (circuit, 0);
|
||||
break;
|
||||
case IF_DOWN_FROM_Z:
|
||||
isis_circuit_if_del (circuit);
|
||||
circuit->state = C_STATE_CONF;
|
||||
isis_event_circuit_state_change (circuit, 0);
|
||||
break;
|
||||
|
|
|
@ -2037,6 +2037,8 @@ lsp_tick (struct thread *thread)
|
|||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit))
|
||||
{
|
||||
if (circuit->state != C_STATE_UP)
|
||||
continue;
|
||||
for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp))
|
||||
{
|
||||
if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit))
|
||||
|
|
|
@ -1916,6 +1916,9 @@ send_hello (struct isis_circuit *circuit, int level)
|
|||
unsigned long len_pointer, length;
|
||||
int retval;
|
||||
|
||||
if (circuit->state != C_STATE_UP || circuit->interface == NULL)
|
||||
return ISIS_WARNING;
|
||||
|
||||
if (circuit->interface->mtu == 0)
|
||||
{
|
||||
zlog_warn ("circuit has zero MTU");
|
||||
|
@ -2222,6 +2225,9 @@ send_csnp (struct isis_circuit *circuit, int level)
|
|||
struct listnode *node;
|
||||
struct isis_lsp *lsp;
|
||||
|
||||
if (circuit->state != C_STATE_UP || circuit->interface == NULL)
|
||||
return ISIS_WARNING;
|
||||
|
||||
memset (start, 0x00, ISIS_SYS_ID_LEN + 2);
|
||||
memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
|
||||
|
||||
|
@ -2387,6 +2393,9 @@ send_psnp (int level, struct isis_circuit *circuit)
|
|||
struct list *list = NULL;
|
||||
struct listnode *node;
|
||||
|
||||
if (circuit->state != C_STATE_UP || circuit->interface == NULL)
|
||||
return ISIS_WARNING;
|
||||
|
||||
if ((circuit->circ_type == CIRCUIT_T_BROADCAST &&
|
||||
!circuit->u.bc.is_dr[level - 1]) ||
|
||||
circuit->circ_type != CIRCUIT_T_BROADCAST)
|
||||
|
@ -2493,8 +2502,9 @@ send_lsp (struct thread *thread)
|
|||
circuit = THREAD_ARG (thread);
|
||||
assert (circuit);
|
||||
|
||||
if (circuit->state == C_STATE_UP)
|
||||
{
|
||||
if (circuit->state != C_STATE_UP || circuit->interface == NULL)
|
||||
return ISIS_WARNING;
|
||||
|
||||
lsp = listgetdata ((node = listhead (circuit->lsp_queue)));
|
||||
|
||||
/*
|
||||
|
@ -2571,7 +2581,6 @@ send_lsp (struct thread *thread)
|
|||
if (listcount (circuit->lsp_queue) > 0)
|
||||
thread_add_timer (master, send_lsp, circuit, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue