/* Execute NSM event process. */ int ospf_nsm_event (struct thread *thread) { int event; int next_state; struct ospf_neighbor *nbr; struct in_addr router_id; int old_state; struct ospf_interface *oi; nbr = THREAD_ARG (thread); event = THREAD_VAL (thread); router_id = nbr->router_id; old_state = nbr->state; oi = nbr->oi ; /* Call function. */ next_state = (*(NSM [nbr->state][event].func))(nbr); /* When event is NSM_KillNbr or InactivityTimer, the neighbor is deleted. */ if (event == NSM_KillNbr || event == NSM_InactivityTimer) { if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: neighbor deleted", IF_NAME (oi), inet_ntoa (router_id)); /* Timers are canceled in ospf_nbr_free, moreover we cannot call nsm_timer_set here because nbr is freed already!!!*/ /*nsm_timer_set (nbr);*/ return 0; } if (! next_state) next_state = NSM [nbr->state][event].next_state; if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (oi), inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_state_msg, nbr->state), ospf_nsm_event_str [event]); /* If state is changed. */ if (next_state != nbr->state) nsm_change_state (nbr, next_state); /* Make sure timer is set. */ nsm_timer_set (nbr); return 0; }
int nsm_kill_nbr (struct ospf_neighbor *nbr) { /* call it here because we cannot call it from ospf_nsm_event */ nsm_change_state (nbr, NSM_Down); /* Reset neighbor. */ /* killing nbr_self is invalid */ assert (nbr != nbr->oi->nbr_self); if (nbr == nbr->oi->nbr_self) return 1; nsm_reset_nbr (nbr); if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) { struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma; nbr_nbma->nbr = NULL; nbr_nbma->state_change = nbr->state_change; nbr->nbr_nbma = NULL; OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, nbr_nbma->v_poll); if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)", IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); } /* Delete neighbor from interface. */ ospf_nbr_delete (nbr); return 0; }
/* Execute NSM event process. */ int ospf_nsm_event (struct thread *thread) { int event; int next_state; struct ospf_neighbor *nbr; nbr = THREAD_ARG (thread); event = THREAD_VAL (thread); if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_state_msg, nbr->state), ospf_nsm_event_str [event]); next_state = NSM [nbr->state][event].next_state; /* Call function. */ if (NSM [nbr->state][event].func != NULL) { int func_state = (*(NSM [nbr->state][event].func))(nbr); if (NSM [nbr->state][event].next_state == NSM_DependUpon) next_state = func_state; else if (func_state) { /* There's a mismatch between the FSM tables and what an FSM * action/state-change function returned. State changes which * do not have conditional/DependUpon next-states should not * try set next_state. */ zlog_warn ("NSM[%s:%s]: %s (%s): " "Warning: action tried to change next_state to %s", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_state_msg, nbr->state), ospf_nsm_event_str [event], LOOKUP (ospf_nsm_state_msg, func_state)); } } assert (next_state != NSM_DependUpon); /* If state is changed. */ if (next_state != nbr->state) { nsm_notice_state_change (nbr, next_state, event); nsm_change_state (nbr, next_state); } /* Make sure timer is set. */ nsm_timer_set (nbr); /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor * is deleted. * * Rather than encode knowledge here of which events lead to NBR * delete, we take our cue from the NSM table, via the dummy * 'Deleted' neighbour state. */ if (nbr->state == NSM_Deleted) ospf_nbr_delete (nbr); return 0; }