int ospf_hello_timer (struct thread *thread) { struct ospf_interface *oi; oi = THREAD_ARG (thread); oi->t_hello = NULL; if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) zlog (NULL, LOG_DEBUG, "ISM[%s]: Timer (Hello timer expire)", IF_NAME (oi)); /* Sending hello packet. */ ospf_hello_send (oi); /* Hello timer set. */ OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, OSPF_IF_PARAM (oi, v_hello)); return 0; }
void nsm_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_debug ("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(%s, %s -> %s): " "scheduling new router-LSA origination", inet_ntoa (nbr->router_id), LOOKUP(ospf_nsm_state_msg, old_state), LOOKUP(ospf_nsm_state_msg, state)); 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? */ }
/* Hook function called after ospf ISM event is occured. And vty's network command invoke this function after making interface structure. */ static void ism_timer_set (struct ospf_interface *oi) { switch (oi->state) { case ISM_Down: /* First entry point of ospf interface state machine. In this state interface parameters must be set to initial values, and timers are reset also. */ OSPF_ISM_TIMER_OFF (oi->t_hello); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_OFF (oi->t_ls_ack); break; case ISM_Loopback: /* In this state, the interface may be looped back and will be unavailable for regular data traffic. */ OSPF_ISM_TIMER_OFF (oi->t_hello); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_OFF (oi->t_ls_ack); break; case ISM_Waiting: /* The router is trying to determine the identity of DRouter and BDRouter. The router begin to receive and send Hello Packets. */ /* send first hello immediately */ OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1); OSPF_ISM_TIMER_ON (oi->t_wait, ospf_wait_timer, OSPF_IF_PARAM (oi, v_wait)); OSPF_ISM_TIMER_OFF (oi->t_ls_ack); break; case ISM_PointToPoint: /* The interface connects to a physical Point-to-point network or virtual link. The router attempts to form an adjacency with neighboring router. Hello packets are also sent. */ /* send first hello immediately */ OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); break; case ISM_DROther: /* The network type of the interface is broadcast or NBMA network, and the router itself is neither Designated Router nor Backup Designated Router. */ OSPF_HELLO_TIMER_ON (oi); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); break; case ISM_Backup: /* The network type of the interface is broadcast os NBMA network, and the router is Backup Designated Router. */ OSPF_HELLO_TIMER_ON (oi); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); break; case ISM_DR: /* The network type of the interface is broadcast or NBMA network, and the router is Designated Router. */ OSPF_HELLO_TIMER_ON (oi); OSPF_ISM_TIMER_OFF (oi->t_wait); OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); break; } }
void nsm_change_status (struct ospf_neighbor *nbr, int status) { int old_status; struct ospf_interface *oi; struct ospf_area *vl_area = NULL; /* Logging change of status. */ if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) zlog_info ("NSM[%s:%s]: Status change %s -> %s", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_status_msg, nbr->status), LOOKUP (ospf_nsm_status_msg, status)); /* Preserve old status. */ old_status = nbr->status; /* Change to new status. */ nbr->status = status; /* Statistics. */ nbr->state_change++; oi = nbr->oi; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) vl_area = ospf_area_lookup_by_area_id (oi->vl_data->vl_area_id); /* One of the neighboring routers changes to/from the FULL state. */ if ((old_status != NSM_Full && status == NSM_Full) || (old_status == NSM_Full && status != NSM_Full)) { if (status == NSM_Full) { oi->full_nbrs++; oi->area->full_nbrs++; ospf_check_abr_status (); if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) if (++vl_area->full_vls == 1) ospf_schedule_abr_task (); } else { oi->full_nbrs--; oi->area->full_nbrs--; ospf_check_abr_status (); if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) if (vl_area->full_vls > 0) if (--vl_area->full_vls == 0) ospf_schedule_abr_task (); /* clear neighbor retransmit list */ if (!ospf_ls_retransmit_isempty (nbr)) ospf_ls_retransmit_clear (nbr); } zlog_info ("nsm_change_status(): " "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->vl_data->vl_area_id); if (vl_area) ospf_router_lsa_timer_add (vl_area); } /* Originate network-LSA. */ if (oi->status == 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); } } /* Start DD exchange protocol */ if (status == 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 (status == NSM_Down) nbr->crypt_seqnum = 0; /* Generete NeighborChange ISM event. */ if ((old_status < NSM_TwoWay && status >= NSM_TwoWay) || (old_status >= NSM_TwoWay && status < NSM_TwoWay)) OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange); /* Performance hack. Send hello immideately when some neighbor enter Init state. This whay we decrease neighbor discovery time. Gleb.*/ if (status == NSM_Init) { OSPF_ISM_TIMER_OFF (oi->t_hello); OSPF_ISM_TIMER_ON (oi->t_hello, ospf_hello_timer, 1); } /* Preserve old status? */ }