diff options
Diffstat (limited to 'ospfd/ospf_nsm.c')
| -rw-r--r-- | ospfd/ospf_nsm.c | 1367 |
1 files changed, 667 insertions, 700 deletions
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index b1f3a838bc..a112f7095a 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -51,49 +51,47 @@ #include "ospfd/ospf_bfd.h" DEFINE_HOOK(ospf_nsm_change, - (struct ospf_neighbor *on, int state, int oldstate), - (on, state, oldstate)) + (struct ospf_neighbor * on, int state, int oldstate), + (on, state, oldstate)) -static void nsm_clear_adj (struct ospf_neighbor *); +static void nsm_clear_adj(struct ospf_neighbor *); /* OSPF NSM Timer functions. */ -static int -ospf_inactivity_timer (struct thread *thread) +static int ospf_inactivity_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_inactivity = NULL; + nbr = THREAD_ARG(thread); + nbr->t_inactivity = NULL; - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (Inactivity timer expire)", - IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (Inactivity timer expire)", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); - return 0; + return 0; } -static int -ospf_db_desc_timer (struct thread *thread) +static int ospf_db_desc_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_db_desc = NULL; + nbr = THREAD_ARG(thread); + nbr->t_db_desc = NULL; - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (DD Retransmit timer expire)", - IF_NAME(nbr->oi), inet_ntoa(nbr->src)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (DD Retransmit timer expire)", + IF_NAME(nbr->oi), inet_ntoa(nbr->src)); - /* resent last send DD packet. */ - assert (nbr->last_send); - ospf_db_desc_resend (nbr); + /* resent last send DD packet. */ + assert(nbr->last_send); + ospf_db_desc_resend(nbr); - /* DD Retransmit timer set. */ - OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); + /* DD Retransmit timer set. */ + OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); - return 0; + return 0; } /* Hook function called after ospf NSM event is occured. @@ -105,175 +103,165 @@ ospf_db_desc_timer (struct thread *thread) * We rely on this function to properly clear timers in lower states, * particularly before deleting a neighbour. */ -static void -nsm_timer_set (struct ospf_neighbor *nbr) +static void nsm_timer_set(struct ospf_neighbor *nbr) { - switch (nbr->state) - { - case NSM_Deleted: - case NSM_Down: - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - OSPF_NSM_TIMER_OFF (nbr->t_hello_reply); - case NSM_Attempt: - case NSM_Init: - case NSM_TwoWay: - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); - OSPF_NSM_TIMER_OFF (nbr->t_ls_req); - break; - case NSM_ExStart: - OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); - OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); - OSPF_NSM_TIMER_OFF (nbr->t_ls_req); - break; - case NSM_Exchange: - OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd); - if (!IS_SET_DD_MS (nbr->dd_flags)) - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - break; - case NSM_Loading: - case NSM_Full: - default: - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - break; - } + switch (nbr->state) { + case NSM_Deleted: + case NSM_Down: + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); + OSPF_NSM_TIMER_OFF(nbr->t_hello_reply); + case NSM_Attempt: + case NSM_Init: + case NSM_TwoWay: + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + OSPF_NSM_TIMER_OFF(nbr->t_ls_upd); + OSPF_NSM_TIMER_OFF(nbr->t_ls_req); + break; + case NSM_ExStart: + OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer, + nbr->v_db_desc); + OSPF_NSM_TIMER_OFF(nbr->t_ls_upd); + OSPF_NSM_TIMER_OFF(nbr->t_ls_req); + break; + case NSM_Exchange: + OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer, + nbr->v_ls_upd); + if (!IS_SET_DD_MS(nbr->dd_flags)) + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + break; + case NSM_Loading: + case NSM_Full: + default: + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + break; + } } /* 10.4 of RFC2328, indicate whether an adjacency is appropriate with * the given neighbour */ -static int -nsm_should_adj (struct ospf_neighbor *nbr) +static int nsm_should_adj(struct ospf_neighbor *nbr) { - struct ospf_interface *oi = nbr->oi; - - /* These network types must always form adjacencies. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT - || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT - || oi->type == OSPF_IFTYPE_VIRTUALLINK - /* Router itself is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)) - /* Neighboring Router is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi))) - return 1; - - return 0; + struct ospf_interface *oi = nbr->oi; + + /* These network types must always form adjacencies. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK + /* Router itself is the DRouter or the BDRouter. */ + || IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi)) + || IPV4_ADDR_SAME(&oi->address->u.prefix4, &BDR(oi)) + /* Neighboring Router is the DRouter or the BDRouter. */ + || IPV4_ADDR_SAME(&nbr->address.u.prefix4, &DR(oi)) + || IPV4_ADDR_SAME(&nbr->address.u.prefix4, &BDR(oi))) + return 1; + + return 0; } /* OSPF NSM functions. */ -static int -nsm_packet_received (struct ospf_neighbor *nbr) +static int nsm_packet_received(struct ospf_neighbor *nbr) { - /* Start or Restart Inactivity Timer. */ - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - - OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, - nbr->v_inactivity); + /* Start or Restart Inactivity Timer. */ + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); + + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); - if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma) - OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF(nbr->nbr_nbma->t_poll); - /* Send proactive ARP requests */ - if (nbr->state < NSM_Exchange) - ospf_proactively_arp (nbr); + /* Send proactive ARP requests */ + if (nbr->state < NSM_Exchange) + ospf_proactively_arp(nbr); - return 0; + return 0; } -static int -nsm_start (struct ospf_neighbor *nbr) +static int nsm_start(struct ospf_neighbor *nbr) { - if (nbr->nbr_nbma) - OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + if (nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF(nbr->nbr_nbma->t_poll); - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - - OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, - nbr->v_inactivity); + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); - return 0; + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + + return 0; } -static int -nsm_twoway_received (struct ospf_neighbor *nbr) +static int nsm_twoway_received(struct ospf_neighbor *nbr) { - int adj = nsm_should_adj (nbr); + int adj = nsm_should_adj(nbr); - /* Send proactive ARP requests */ - if (adj) - ospf_proactively_arp (nbr); + /* Send proactive ARP requests */ + if (adj) + ospf_proactively_arp(nbr); - return (adj ? NSM_ExStart : NSM_TwoWay); + return (adj ? NSM_ExStart : NSM_TwoWay); } -int -ospf_db_summary_count (struct ospf_neighbor *nbr) +int ospf_db_summary_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->db_sum); + return ospf_lsdb_count_all(&nbr->db_sum); } -int -ospf_db_summary_isempty (struct ospf_neighbor *nbr) +int ospf_db_summary_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->db_sum); + return ospf_lsdb_isempty(&nbr->db_sum); } -static int -ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +static int ospf_db_summary_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */ - if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi) - return 0; - break; - case OSPF_OPAQUE_AREA_LSA: - /* - * It is assured by the caller function "nsm_negotiation_done()" - * that every given LSA belongs to the same area with "nbr". - */ - break; - case OSPF_OPAQUE_AS_LSA: - default: - break; - } - - /* Stay away from any Local Translated Type-7 LSAs */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - return 0; - - if (IS_LSA_MAXAGE (lsa)) - ospf_ls_retransmit_add (nbr, lsa); - else - ospf_lsdb_add (&nbr->db_sum, lsa); - - return 0; + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + /* Exclude type-9 LSAs that does not have the same "oi" with + * "nbr". */ + if (nbr->oi && ospf_if_exists(lsa->oi) != nbr->oi) + return 0; + break; + case OSPF_OPAQUE_AREA_LSA: + /* + * It is assured by the caller function "nsm_negotiation_done()" + * that every given LSA belongs to the same area with "nbr". + */ + break; + case OSPF_OPAQUE_AS_LSA: + default: + break; + } + + /* Stay away from any Local Translated Type-7 LSAs */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + return 0; + + if (IS_LSA_MAXAGE(lsa)) + ospf_ls_retransmit_add(nbr, lsa); + else + ospf_lsdb_add(&nbr->db_sum, lsa); + + return 0; } -void -ospf_db_summary_clear (struct ospf_neighbor *nbr) +void ospf_db_summary_clear(struct ospf_neighbor *nbr) { - struct ospf_lsdb *lsdb; - int i; - - lsdb = &nbr->db_sum; - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rn->info) - ospf_lsdb_delete (&nbr->db_sum, rn->info); - } -} + struct ospf_lsdb *lsdb; + int i; + lsdb = &nbr->db_sum; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + + for (rn = route_top(table); rn; rn = route_next(rn)) + if (rn->info) + ospf_lsdb_delete(&nbr->db_sum, rn->info); + } +} /* The area link state database consists of the router-LSAs, @@ -282,598 +270,577 @@ ospf_db_summary_clear (struct ospf_neighbor *nbr) AS-external-LSAs are omitted from a virtual neighbor's Database summary list. AS-external-LSAs are omitted from the Database summary list if the area has been configured as a stub. */ -static int -nsm_negotiation_done (struct ospf_neighbor *nbr) +static int nsm_negotiation_done(struct ospf_neighbor *nbr) { - struct ospf_area *area = nbr->oi->area; - struct ospf_lsa *lsa; - struct route_node *rn; - - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); - - LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - /* Process only if the neighbor is opaque capable. */ - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - { - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - } - - if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP)) - { - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - } - - if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK - && area->external_routing == OSPF_AREA_DEFAULT) - LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O) - && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK - && area->external_routing == OSPF_AREA_DEFAULT)) - LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - return 0; + struct ospf_area *area = nbr->oi->area; + struct ospf_lsa *lsa; + struct route_node *rn; + + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + /* Process only if the neighbor is opaque capable. */ + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + } + + if (CHECK_FLAG(nbr->options, OSPF_OPTION_NP)) { + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + } + + if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT) + LSDB_LOOP(EXTERNAL_LSDB(nbr->oi->ospf), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O) + && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT)) + LSDB_LOOP(OPAQUE_AS_LSDB(nbr->oi->ospf), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + return 0; } -static int -nsm_exchange_done (struct ospf_neighbor *nbr) +static int nsm_exchange_done(struct ospf_neighbor *nbr) { - if (ospf_ls_request_isempty (nbr)) - return NSM_Full; + if (ospf_ls_request_isempty(nbr)) + return NSM_Full; - /* Send Link State Request. */ - if (nbr->t_ls_req == NULL) - ospf_ls_req_send (nbr); + /* Send Link State Request. */ + if (nbr->t_ls_req == NULL) + ospf_ls_req_send(nbr); - return NSM_Loading; + return NSM_Loading; } -static int -nsm_adj_ok (struct ospf_neighbor *nbr) +static int nsm_adj_ok(struct ospf_neighbor *nbr) { - int next_state = nbr->state; - int adj = nsm_should_adj (nbr); + int next_state = nbr->state; + int adj = nsm_should_adj(nbr); - if (nbr->state == NSM_TwoWay && adj == 1) - { - next_state = NSM_ExStart; + if (nbr->state == NSM_TwoWay && adj == 1) { + next_state = NSM_ExStart; - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); - } - else if (nbr->state >= NSM_ExStart && adj == 0) - next_state = NSM_TwoWay; + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + } else if (nbr->state >= NSM_ExStart && adj == 0) + next_state = NSM_TwoWay; - return next_state; + return next_state; } /* Clear adjacency related state for a neighbour, intended where nbr * transitions from > ExStart (i.e. a Full or forming adjacency) * to <= ExStart. */ -static void -nsm_clear_adj (struct ospf_neighbor *nbr) +static void nsm_clear_adj(struct ospf_neighbor *nbr) { - /* Clear Database Summary list. */ - if (!ospf_db_summary_isempty (nbr)) - ospf_db_summary_clear (nbr); + /* Clear Database Summary list. */ + if (!ospf_db_summary_isempty(nbr)) + ospf_db_summary_clear(nbr); - /* Clear Link State Request list. */ - if (!ospf_ls_request_isempty (nbr)) - ospf_ls_request_delete_all (nbr); + /* Clear Link State Request list. */ + if (!ospf_ls_request_isempty(nbr)) + ospf_ls_request_delete_all(nbr); - /* Clear Link State Retransmission list. */ - if (!ospf_ls_retransmit_isempty (nbr)) - ospf_ls_retransmit_clear (nbr); + /* Clear Link State Retransmission list. */ + if (!ospf_ls_retransmit_isempty(nbr)) + ospf_ls_retransmit_clear(nbr); - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - UNSET_FLAG (nbr->options, OSPF_OPTION_O); + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) + UNSET_FLAG(nbr->options, OSPF_OPTION_O); } -static int -nsm_kill_nbr (struct ospf_neighbor *nbr) +static int nsm_kill_nbr(struct ospf_neighbor *nbr) { - /* killing nbr_self is invalid */ - if (nbr == nbr->oi->nbr_self) - { - assert (nbr != nbr->oi->nbr_self); - return 0; - } - - 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)); - } - - return 0; + /* killing nbr_self is invalid */ + if (nbr == nbr->oi->nbr_self) { + assert(nbr != nbr->oi->nbr_self); + return 0; + } + + 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)); + } + + return 0; } /* Neighbor State Machine */ struct { - int (*func) (struct ospf_neighbor *); - int next_state; -} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] = -{ - { - /* DependUpon: dummy state. */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { NULL, NSM_DependUpon }, /* PacketReceived */ - { NULL, NSM_DependUpon }, /* Start */ - { NULL, NSM_DependUpon }, /* 2-WayReceived */ - { NULL, NSM_DependUpon }, /* NegotiationDone */ - { NULL, NSM_DependUpon }, /* ExchangeDone */ - { NULL, NSM_DependUpon }, /* BadLSReq */ - { NULL, NSM_DependUpon }, /* LoadingDone */ - { NULL, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_DependUpon }, /* SeqNumberMismatch */ - { NULL, NSM_DependUpon }, /* 1-WayReceived */ - { NULL, NSM_DependUpon }, /* KillNbr */ - { NULL, NSM_DependUpon }, /* InactivityTimer */ - { NULL, NSM_DependUpon }, /* LLDown */ - }, - { - /* Deleted: dummy state. */ - { NULL, NSM_Deleted }, /* NoEvent */ - { NULL, NSM_Deleted }, /* PacketReceived */ - { NULL, NSM_Deleted }, /* Start */ - { NULL, NSM_Deleted }, /* 2-WayReceived */ - { NULL, NSM_Deleted }, /* NegotiationDone */ - { NULL, NSM_Deleted }, /* ExchangeDone */ - { NULL, NSM_Deleted }, /* BadLSReq */ - { NULL, NSM_Deleted }, /* LoadingDone */ - { NULL, NSM_Deleted }, /* AdjOK? */ - { NULL, NSM_Deleted }, /* SeqNumberMismatch */ - { NULL, NSM_Deleted }, /* 1-WayReceived */ - { NULL, NSM_Deleted }, /* KillNbr */ - { NULL, NSM_Deleted }, /* InactivityTimer */ - { NULL, NSM_Deleted }, /* LLDown */ - }, - { - /* Down: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { nsm_start, NSM_Attempt }, /* Start */ - { NULL, NSM_Down }, /* 2-WayReceived */ - { NULL, NSM_Down }, /* NegotiationDone */ - { NULL, NSM_Down }, /* ExchangeDone */ - { NULL, NSM_Down }, /* BadLSReq */ - { NULL, NSM_Down }, /* LoadingDone */ - { NULL, NSM_Down }, /* AdjOK? */ - { NULL, NSM_Down }, /* SeqNumberMismatch */ - { NULL, NSM_Down }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Attempt: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { NULL, NSM_Attempt }, /* Start */ - { NULL, NSM_Attempt }, /* 2-WayReceived */ - { NULL, NSM_Attempt }, /* NegotiationDone */ - { NULL, NSM_Attempt }, /* ExchangeDone */ - { NULL, NSM_Attempt }, /* BadLSReq */ - { NULL, NSM_Attempt }, /* LoadingDone */ - { NULL, NSM_Attempt }, /* AdjOK? */ - { NULL, NSM_Attempt }, /* SeqNumberMismatch */ - { NULL, NSM_Attempt }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Init: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { NULL, NSM_Init }, /* Start */ - { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ - { NULL, NSM_Init }, /* NegotiationDone */ - { NULL, NSM_Init }, /* ExchangeDone */ - { NULL, NSM_Init }, /* BadLSReq */ - { NULL, NSM_Init }, /* LoadingDone */ - { NULL, NSM_Init }, /* AdjOK? */ - { NULL, NSM_Init }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* 2-Way: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */ - { NULL, NSM_TwoWay }, /* Start */ - { NULL, NSM_TwoWay }, /* 2-WayReceived */ - { NULL, NSM_TwoWay }, /* NegotiationDone */ - { NULL, NSM_TwoWay }, /* ExchangeDone */ - { NULL, NSM_TwoWay }, /* BadLSReq */ - { NULL, NSM_TwoWay }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_TwoWay }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* ExStart: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */ - { NULL, NSM_ExStart }, /* Start */ - { NULL, NSM_ExStart }, /* 2-WayReceived */ - { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ - { NULL, NSM_ExStart }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_ExStart }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Exchange: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Exchange }, /* PacketReceived */ - { NULL, NSM_Exchange }, /* Start */ - { NULL, NSM_Exchange }, /* 2-WayReceived */ - { NULL, NSM_Exchange }, /* NegotiationDone */ - { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Exchange }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Loading: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Loading }, /* PacketReceived */ - { NULL, NSM_Loading }, /* Start */ - { NULL, NSM_Loading }, /* 2-WayReceived */ - { NULL, NSM_Loading }, /* NegotiationDone */ - { NULL, NSM_Loading }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Full }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { /* Full: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Full }, /* PacketReceived */ - { NULL, NSM_Full }, /* Start */ - { NULL, NSM_Full }, /* 2-WayReceived */ - { NULL, NSM_Full }, /* NegotiationDone */ - { NULL, NSM_Full }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Full }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, + int (*func)(struct ospf_neighbor *); + int next_state; +} NSM[OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] = { + { + /* DependUpon: dummy state. */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {NULL, NSM_DependUpon}, /* PacketReceived */ + {NULL, NSM_DependUpon}, /* Start */ + {NULL, NSM_DependUpon}, /* 2-WayReceived */ + {NULL, NSM_DependUpon}, /* NegotiationDone */ + {NULL, NSM_DependUpon}, /* ExchangeDone */ + {NULL, NSM_DependUpon}, /* BadLSReq */ + {NULL, NSM_DependUpon}, /* LoadingDone */ + {NULL, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_DependUpon}, /* SeqNumberMismatch */ + {NULL, NSM_DependUpon}, /* 1-WayReceived */ + {NULL, NSM_DependUpon}, /* KillNbr */ + {NULL, NSM_DependUpon}, /* InactivityTimer */ + {NULL, NSM_DependUpon}, /* LLDown */ + }, + { + /* Deleted: dummy state. */ + {NULL, NSM_Deleted}, /* NoEvent */ + {NULL, NSM_Deleted}, /* PacketReceived */ + {NULL, NSM_Deleted}, /* Start */ + {NULL, NSM_Deleted}, /* 2-WayReceived */ + {NULL, NSM_Deleted}, /* NegotiationDone */ + {NULL, NSM_Deleted}, /* ExchangeDone */ + {NULL, NSM_Deleted}, /* BadLSReq */ + {NULL, NSM_Deleted}, /* LoadingDone */ + {NULL, NSM_Deleted}, /* AdjOK? */ + {NULL, NSM_Deleted}, /* SeqNumberMismatch */ + {NULL, NSM_Deleted}, /* 1-WayReceived */ + {NULL, NSM_Deleted}, /* KillNbr */ + {NULL, NSM_Deleted}, /* InactivityTimer */ + {NULL, NSM_Deleted}, /* LLDown */ + }, + { + /* Down: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_start, NSM_Attempt}, /* Start */ + {NULL, NSM_Down}, /* 2-WayReceived */ + {NULL, NSM_Down}, /* NegotiationDone */ + {NULL, NSM_Down}, /* ExchangeDone */ + {NULL, NSM_Down}, /* BadLSReq */ + {NULL, NSM_Down}, /* LoadingDone */ + {NULL, NSM_Down}, /* AdjOK? */ + {NULL, NSM_Down}, /* SeqNumberMismatch */ + {NULL, NSM_Down}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Attempt: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {NULL, NSM_Attempt}, /* Start */ + {NULL, NSM_Attempt}, /* 2-WayReceived */ + {NULL, NSM_Attempt}, /* NegotiationDone */ + {NULL, NSM_Attempt}, /* ExchangeDone */ + {NULL, NSM_Attempt}, /* BadLSReq */ + {NULL, NSM_Attempt}, /* LoadingDone */ + {NULL, NSM_Attempt}, /* AdjOK? */ + {NULL, NSM_Attempt}, /* SeqNumberMismatch */ + {NULL, NSM_Attempt}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Init: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {NULL, NSM_Init}, /* Start */ + {nsm_twoway_received, NSM_DependUpon}, /* 2-WayReceived */ + {NULL, NSM_Init}, /* NegotiationDone */ + {NULL, NSM_Init}, /* ExchangeDone */ + {NULL, NSM_Init}, /* BadLSReq */ + {NULL, NSM_Init}, /* LoadingDone */ + {NULL, NSM_Init}, /* AdjOK? */ + {NULL, NSM_Init}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* 2-Way: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_TwoWay}, /* HelloReceived */ + {NULL, NSM_TwoWay}, /* Start */ + {NULL, NSM_TwoWay}, /* 2-WayReceived */ + {NULL, NSM_TwoWay}, /* NegotiationDone */ + {NULL, NSM_TwoWay}, /* ExchangeDone */ + {NULL, NSM_TwoWay}, /* BadLSReq */ + {NULL, NSM_TwoWay}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_TwoWay}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* ExStart: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_ExStart}, /* PacaketReceived */ + {NULL, NSM_ExStart}, /* Start */ + {NULL, NSM_ExStart}, /* 2-WayReceived */ + {nsm_negotiation_done, NSM_Exchange}, /* NegotiationDone */ + {NULL, NSM_ExStart}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_ExStart}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Exchange: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Exchange}, /* PacketReceived */ + {NULL, NSM_Exchange}, /* Start */ + {NULL, NSM_Exchange}, /* 2-WayReceived */ + {NULL, NSM_Exchange}, /* NegotiationDone */ + {nsm_exchange_done, NSM_DependUpon}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Exchange}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Loading: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Loading}, /* PacketReceived */ + {NULL, NSM_Loading}, /* Start */ + {NULL, NSM_Loading}, /* 2-WayReceived */ + {NULL, NSM_Loading}, /* NegotiationDone */ + {NULL, NSM_Loading}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Full}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Full: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Full}, /* PacketReceived */ + {NULL, NSM_Full}, /* Start */ + {NULL, NSM_Full}, /* 2-WayReceived */ + {NULL, NSM_Full}, /* NegotiationDone */ + {NULL, NSM_Full}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Full}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, }; -static const char *ospf_nsm_event_str[] = -{ - "NoEvent", - "PacketReceived", - "Start", - "2-WayReceived", - "NegotiationDone", - "ExchangeDone", - "BadLSReq", - "LoadingDone", - "AdjOK?", - "SeqNumberMismatch", - "1-WayReceived", - "KillNbr", - "InactivityTimer", - "LLDown", +static const char *ospf_nsm_event_str[] = { + "NoEvent", "PacketReceived", "Start", + "2-WayReceived", "NegotiationDone", "ExchangeDone", + "BadLSReq", "LoadingDone", "AdjOK?", + "SeqNumberMismatch", "1-WayReceived", "KillNbr", + "InactivityTimer", "LLDown", }; -static void -nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event) +static void nsm_notice_state_change(struct ospf_neighbor *nbr, int next_state, + int event) { - /* Logging change of status. */ - if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) - zlog_debug ("NSM[%s:%s]: State change %s -> %s (%s)", - IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - lookup_msg(ospf_nsm_state_msg, next_state, NULL), - ospf_nsm_event_str [event]); - - /* Optionally notify about adjacency changes */ - if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) && - (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) || - (next_state == NSM_Full) || (next_state < nbr->state))) - zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)", - inet_ntoa (nbr->router_id), IF_NAME (nbr->oi), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - lookup_msg(ospf_nsm_state_msg, next_state, NULL), - ospf_nsm_event_str [event]); - - /* Advance in NSM */ - if (next_state > nbr->state) - monotime(&nbr->ts_last_progress); - else /* regression in NSM */ - { - monotime(&nbr->ts_last_regress); - nbr->last_regress_str = ospf_nsm_event_str [event]; - } - + /* Logging change of status. */ + if (IS_DEBUG_OSPF(nsm, NSM_STATUS)) + zlog_debug("NSM[%s:%s]: State change %s -> %s (%s)", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + lookup_msg(ospf_nsm_state_msg, next_state, NULL), + ospf_nsm_event_str[event]); + + /* Optionally notify about adjacency changes */ + if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) + && (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) + || (next_state == NSM_Full) || (next_state < nbr->state))) + zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)", + inet_ntoa(nbr->router_id), IF_NAME(nbr->oi), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + lookup_msg(ospf_nsm_state_msg, next_state, NULL), + ospf_nsm_event_str[event]); + + /* Advance in NSM */ + if (next_state > nbr->state) + monotime(&nbr->ts_last_progress); + else /* regression in NSM */ + { + monotime(&nbr->ts_last_regress); + nbr->last_regress_str = ospf_nsm_event_str[event]; + } } -static void -nsm_change_state (struct ospf_neighbor *nbr, int state) +static 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; - - /* 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); - - /* Generate NeighborChange ISM event. - * - * In response to NeighborChange, DR election is rerun. The information - * from the election process is required by the router-lsa construction. - * - * Therefore, trigger the event prior to refreshing the LSAs. */ - 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; - } - - /* 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++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - if (x == ZEBRA_ROUTE_OSPF6) - continue; - - red_list = oi->ospf->redist[x]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - ospf_external_lsa_refresh_type (oi->ospf, x, red->instance, force); - } - /* XXX: Clearly some thing is wrong with refresh of external LSAs - * this added to hack around defaults not refreshing after a timer - * jump. - */ - ospf_external_lsa_refresh_default (oi->ospf); + struct ospf_interface *oi = nbr->oi; + struct ospf_area *vl_area = NULL; + u_char old_state; + int x; + int force = 1; + + /* 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); + + /* Generate NeighborChange ISM event. + * + * In response to NeighborChange, DR election is rerun. The information + * from the election process is required by the router-lsa construction. + * + * Therefore, trigger the event prior to refreshing the LSAs. */ + 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; } - else - { - oi->full_nbrs--; - oi->area->full_nbrs--; - ospf_check_abr_status (oi->ospf); + /* 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++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + if (x == ZEBRA_ROUTE_OSPF6) + continue; + + red_list = oi->ospf->redist[x]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + ospf_external_lsa_refresh_type( + oi->ospf, x, red->instance, + force); + } + /* XXX: Clearly some thing is wrong with refresh of + * external LSAs + * this added to hack around defaults not refreshing + * after a timer + * jump. + */ + ospf_external_lsa_refresh_default(oi->ospf); + } 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); + } + + zlog_info( + "nsm_change_state(%s, %s -> %s): " + "scheduling new router-LSA origination", + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, old_state, NULL), + lookup_msg(ospf_nsm_state_msg, state, NULL)); + + ospf_router_lsa_update_area(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_update_area(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; + } else + ospf_network_lsa_update(oi); + } + } - 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); + ospf_opaque_nsm_change(nbr, old_state); + + /* State changes from > ExStart to <= ExStart should clear any Exchange + * or Full/LSA Update related lists and state. + * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK? + */ + if ((old_state > NSM_ExStart) && (state <= NSM_ExStart)) + nsm_clear_adj(nbr); + + /* Start DD exchange protocol */ + if (state == NSM_ExStart) { + if (nbr->dd_seqnum == 0) + nbr->dd_seqnum = (uint32_t)random(); + else + nbr->dd_seqnum++; + + nbr->dd_flags = + OSPF_DD_FLAG_I | OSPF_DD_FLAG_M | OSPF_DD_FLAG_MS; + ospf_db_desc_send(nbr); } - zlog_info ("nsm_change_state(%s, %s -> %s): " - "scheduling new router-LSA origination", - inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, old_state, NULL), - lookup_msg(ospf_nsm_state_msg, state, NULL)); + /* clear cryptographic sequence number */ + if (state == NSM_Down) + nbr->crypt_seqnum = 0; - ospf_router_lsa_update_area (oi->area); + ospf_bfd_trigger_event(nbr, old_state, state); - 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_update_area (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; - } - else - ospf_network_lsa_update (oi); - } - } - - ospf_opaque_nsm_change (nbr, old_state); - - /* State changes from > ExStart to <= ExStart should clear any Exchange - * or Full/LSA Update related lists and state. - * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK? - */ - if ((old_state > NSM_ExStart) && (state <= NSM_ExStart)) - nsm_clear_adj (nbr); - - /* Start DD exchange protocol */ - if (state == NSM_ExStart) - { - if (nbr->dd_seqnum == 0) - nbr->dd_seqnum = (uint32_t)random (); - 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; - - ospf_bfd_trigger_event(nbr, old_state, state); - - /* Preserve old status? */ + /* Preserve old status? */ } /* Execute NSM event process. */ -int -ospf_nsm_event (struct thread *thread) +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_msg(ospf_nsm_state_msg, nbr->state, NULL), - 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_msg(ospf_nsm_state_msg, nbr->state, NULL), - ospf_nsm_event_str [event], - lookup_msg(ospf_nsm_state_msg, func_state, NULL)); - } - } - - assert (next_state != NSM_DependUpon); - - /* If state is changed. */ - if (next_state != nbr->state) - { - int old_state = nbr->state; - - nsm_notice_state_change (nbr, next_state, event); - nsm_change_state (nbr, next_state); - - hook_call(ospf_nsm_change, nbr, next_state, old_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; + 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_msg(ospf_nsm_state_msg, nbr->state, NULL), + 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_msg(ospf_nsm_state_msg, nbr->state, + NULL), + ospf_nsm_event_str[event], + lookup_msg(ospf_nsm_state_msg, func_state, + NULL)); + } + } + + assert(next_state != NSM_DependUpon); + + /* If state is changed. */ + if (next_state != nbr->state) { + int old_state = nbr->state; + + nsm_notice_state_change(nbr, next_state, event); + nsm_change_state(nbr, next_state); + + hook_call(ospf_nsm_change, nbr, next_state, old_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; } /* Check loading state. */ -void -ospf_check_nbr_loading (struct ospf_neighbor *nbr) +void ospf_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); - } + 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); + } } |
