📄 ospf_nsm.c
字号:
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_info ("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;}intnsm_inactivity_timer (struct ospf_neighbor *nbr){ /* Kill neighbor. */ nsm_kill_nbr (nbr); return 0;}intnsm_ll_down (struct ospf_neighbor *nbr){ /* Reset neighbor. */ /*nsm_reset_nbr (nbr);*/ /* Kill neighbor. */ nsm_kill_nbr (nbr); return 0;}/* Neighbor State Machine */struct { int (*func) (); int next_state;} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] ={ { /* DependUpon: dummy state. */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_ignore, NSM_DependUpon }, /* HelloReceived */ { nsm_ignore, NSM_DependUpon }, /* Start */ { nsm_ignore, NSM_DependUpon }, /* 2-WayReceived */ { nsm_ignore, NSM_DependUpon }, /* NegotiationDone */ { nsm_ignore, NSM_DependUpon }, /* ExchangeDone */ { nsm_ignore, NSM_DependUpon }, /* BadLSReq */ { nsm_ignore, NSM_DependUpon }, /* LoadingDone */ { nsm_ignore, NSM_DependUpon }, /* AdjOK? */ { nsm_ignore, NSM_DependUpon }, /* SeqNumberMismatch */ { nsm_ignore, NSM_DependUpon }, /* 1-WayReceived */ { nsm_ignore, NSM_DependUpon }, /* KillNbr */ { nsm_ignore, NSM_DependUpon }, /* InactivityTimer */ { nsm_ignore, NSM_DependUpon }, /* LLDown */ }, { /* Down: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Init }, /* HelloReceived */ { nsm_start, NSM_Attempt }, /* Start */ { nsm_ignore, NSM_Down }, /* 2-WayReceived */ { nsm_ignore, NSM_Down }, /* NegotiationDone */ { nsm_ignore, NSM_Down }, /* ExchangeDone */ { nsm_ignore, NSM_Down }, /* BadLSReq */ { nsm_ignore, NSM_Down }, /* LoadingDone */ { nsm_ignore, NSM_Down }, /* AdjOK? */ { nsm_ignore, NSM_Down }, /* SeqNumberMismatch */ { nsm_ignore, NSM_Down }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* Attempt: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Init }, /* HelloReceived */ { nsm_ignore, NSM_Attempt }, /* Start */ { nsm_ignore, NSM_Attempt }, /* 2-WayReceived */ { nsm_ignore, NSM_Attempt }, /* NegotiationDone */ { nsm_ignore, NSM_Attempt }, /* ExchangeDone */ { nsm_ignore, NSM_Attempt }, /* BadLSReq */ { nsm_ignore, NSM_Attempt }, /* LoadingDone */ { nsm_ignore, NSM_Attempt }, /* AdjOK? */ { nsm_ignore, NSM_Attempt }, /* SeqNumberMismatch */ { nsm_ignore, NSM_Attempt }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* Init: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Init }, /* HelloReceived */ { nsm_ignore, NSM_Init }, /* Start */ { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ { nsm_ignore, NSM_Init }, /* NegotiationDone */ { nsm_ignore, NSM_Init }, /* ExchangeDone */ { nsm_ignore, NSM_Init }, /* BadLSReq */ { nsm_ignore, NSM_Init }, /* LoadingDone */ { nsm_ignore, NSM_Init }, /* AdjOK? */ { nsm_ignore, NSM_Init }, /* SeqNumberMismatch */ { nsm_ignore, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* 2-Way: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_TwoWay }, /* HelloReceived */ { nsm_ignore, NSM_TwoWay }, /* Start */ { nsm_ignore, NSM_TwoWay }, /* 2-WayReceived */ { nsm_ignore, NSM_TwoWay }, /* NegotiationDone */ { nsm_ignore, NSM_TwoWay }, /* ExchangeDone */ { nsm_ignore, NSM_TwoWay }, /* BadLSReq */ { nsm_ignore, NSM_TwoWay }, /* LoadingDone */ { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ { nsm_ignore, NSM_TwoWay }, /* SeqNumberMismatch */ { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* ExStart: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_ExStart }, /* HelloReceived */ { nsm_ignore, NSM_ExStart }, /* Start */ { nsm_ignore, NSM_ExStart }, /* 2-WayReceived */ { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ { nsm_ignore, NSM_ExStart }, /* ExchangeDone */ { nsm_ignore, NSM_ExStart }, /* BadLSReq */ { nsm_ignore, NSM_ExStart }, /* LoadingDone */ { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ { nsm_ignore, NSM_ExStart }, /* SeqNumberMismatch */ { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* Exchange: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Exchange }, /* HelloReceived */ { nsm_ignore, NSM_Exchange }, /* Start */ { nsm_ignore, NSM_Exchange }, /* 2-WayReceived */ { nsm_ignore, NSM_Exchange }, /* NegotiationDone */ { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */ { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ { nsm_ignore, NSM_Exchange }, /* LoadingDone */ { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* Loading: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Loading }, /* HelloReceived */ { nsm_ignore, NSM_Loading }, /* Start */ { nsm_ignore, NSM_Loading }, /* 2-WayReceived */ { nsm_ignore, NSM_Loading }, /* NegotiationDone */ { nsm_ignore, NSM_Loading }, /* ExchangeDone */ { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ { nsm_ignore, NSM_Full }, /* LoadingDone */ { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ }, { /* Full: */ { nsm_ignore, NSM_DependUpon }, /* NoEvent */ { nsm_hello_received, NSM_Full }, /* HelloReceived */ { nsm_ignore, NSM_Full }, /* Start */ { nsm_ignore, NSM_Full }, /* 2-WayReceived */ { nsm_ignore, NSM_Full }, /* NegotiationDone */ { nsm_ignore, NSM_Full }, /* ExchangeDone */ { nsm_bad_ls_req, NSM_ExStart }, /* BadLSReq */ { nsm_ignore, NSM_Full }, /* LoadingDone */ { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ { nsm_seq_number_mismatch, NSM_ExStart }, /* SeqNumberMismatch */ { nsm_oneway_received, NSM_Init }, /* 1-WayReceived */ { nsm_kill_nbr, NSM_Down }, /* KillNbr */ { nsm_inactivity_timer, NSM_Down }, /* InactivityTimer */ { nsm_ll_down, NSM_Down }, /* LLDown */ },};static char *ospf_nsm_event_str[] ={ "NoEvent", "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone", "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived", "KillNbr", "InactivityTimer", "LLDown",};voidnsm_change_state (struct ospf_neighbor *nbr, int state){ struct ospf_interface *oi = nbr->oi; struct ospf_area *vl_area = NULL; u_char old_state; int x; int force = 1; /* Logging change of status. */ if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) zlog_info ("NSM[%s:%s]: State change %s -> %s", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_state_msg, nbr->state), LOOKUP (ospf_nsm_state_msg, state)); /* Preserve old status. */ old_state = nbr->state; /* Change to new status. */ nbr->state = state; /* Statistics. */ nbr->state_change++; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); /* One of the neighboring routers changes to/from the FULL state. */ if ((old_state != NSM_Full && state == NSM_Full) || (old_state == NSM_Full && state != NSM_Full)) { if (state == NSM_Full) { oi->full_nbrs++; oi->area->full_nbrs++; ospf_check_abr_status (oi->ospf); if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) if (++vl_area->full_vls == 1) ospf_schedule_abr_task (oi->ospf); /* kevinm: refresh any redistributions */ for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) { if (x == ZEBRA_ROUTE_OSPF || x == ZEBRA_ROUTE_OSPF6) continue; ospf_external_lsa_refresh_type (oi->ospf, x, force); } } else { oi->full_nbrs--; oi->area->full_nbrs--; ospf_check_abr_status (oi->ospf); if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) if (vl_area->full_vls > 0) if (--vl_area->full_vls == 0) ospf_schedule_abr_task (oi->ospf); /* clear neighbor retransmit list */ if (!ospf_ls_retransmit_isempty (nbr)) ospf_ls_retransmit_clear (nbr); } zlog_info ("nsm_change_state(): " "scheduling new router-LSA origination"); ospf_router_lsa_timer_add (oi->area); if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { struct ospf_area *vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); if (vl_area) ospf_router_lsa_timer_add (vl_area); } /* Originate network-LSA. */ if (oi->state == ISM_DR) { if (oi->network_lsa_self && oi->full_nbrs == 0) { ospf_lsa_flush_area (oi->network_lsa_self, oi->area); ospf_lsa_unlock (oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); } else ospf_network_lsa_timer_add (oi); } }#ifdef HAVE_OPAQUE_LSA ospf_opaque_nsm_change (nbr, old_state);#endif /* HAVE_OPAQUE_LSA */ /* Start DD exchange protocol */ if (state == NSM_ExStart) { if (nbr->dd_seqnum == 0) nbr->dd_seqnum = time (NULL); else nbr->dd_seqnum++; nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS; ospf_db_desc_send (nbr); } /* clear cryptographic sequence number */ if (state == NSM_Down) nbr->crypt_seqnum = 0; /* Generete NeighborChange ISM event. */#ifdef BUGGY_ISM_TRANSITION if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) || (old_state >= NSM_TwoWay && state < NSM_TwoWay)) OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange);#else /* BUGGY_ISM_TRANSITION */ switch (oi->state) { case ISM_DROther: case ISM_Backup: case ISM_DR: if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) || (old_state >= NSM_TwoWay && state < NSM_TwoWay)) OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange); break; default: /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */ break; }#endif /* BUGGY_ISM_TRANSITION */ /* Performance hack. Send hello immideately when some neighbor enter Init state. This whay we decrease neighbor discovery time. Gleb.*/ if (state == NSM_Init) { OSPF_ISM_TIMER_OFF (oi->t_hello); OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1); } /* Preserve old status? */}/* Execute NSM event process. */intospf_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_info ("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_info ("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;}/* Check loading state. */voidospf_check_nbr_loading (struct ospf_neighbor *nbr){ if (nbr->state == NSM_Loading) { if (ospf_ls_request_isempty (nbr)) OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone); else if (nbr->ls_req_last == NULL) ospf_ls_req_event (nbr); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -