X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ospfd%2Fospf_ism.c;h=e394b6f472b4f58f2d4439a46c817a269b9245bb;hb=c84355a93212939e98084137aa927ab911305614;hp=b536491d8af0e7dd9c7d2a16d059560e6d31ada0;hpb=9e3b206d7c25902cd3917d8969f16d118c8fea91;p=mirror_frr.git diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index b536491d8..e394b6f47 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -1,6 +1,6 @@ /* * OSPF version 2 Interface State Machine - * From RFC2328 [OSPF Version 2] + * From RFC2328 [OSPF Version 2] * Copyright (C) 1999, 2000 Toshiaki Takada * * This file is part of GNU Zebra. @@ -44,578 +44,558 @@ #include "ospfd/ospf_abr.h" DEFINE_HOOK(ospf_ism_change, - (struct ospf_interface *oi, int state, int oldstate), - (oi, state, oldstate)) + (struct ospf_interface * oi, int state, int oldstate), + (oi, state, oldstate)) /* elect DR and BDR. Refer to RFC2319 section 9.4 */ -static struct ospf_neighbor * -ospf_dr_election_sub (struct list *routers) +static struct ospf_neighbor *ospf_dr_election_sub(struct list *routers) { - struct listnode *node; - struct ospf_neighbor *nbr, *max = NULL; - - /* Choose highest router priority. - In case of tie, choose highest Router ID. */ - for (ALL_LIST_ELEMENTS_RO (routers, node, nbr)) - { - if (max == NULL) - max = nbr; - else - { - if (max->priority < nbr->priority) - max = nbr; - else if (max->priority == nbr->priority) - if (IPV4_ADDR_CMP (&max->router_id, &nbr->router_id) < 0) - max = nbr; + struct listnode *node; + struct ospf_neighbor *nbr, *max = NULL; + + /* Choose highest router priority. + In case of tie, choose highest Router ID. */ + for (ALL_LIST_ELEMENTS_RO(routers, node, nbr)) { + if (max == NULL) + max = nbr; + else { + if (max->priority < nbr->priority) + max = nbr; + else if (max->priority == nbr->priority) + if (IPV4_ADDR_CMP(&max->router_id, + &nbr->router_id) + < 0) + max = nbr; + } } - } - return max; + return max; } -static struct ospf_neighbor * -ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) +static struct ospf_neighbor *ospf_elect_dr(struct ospf_interface *oi, + struct list *el_list) { - struct list *dr_list; - struct listnode *node; - struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL; - - dr_list = list_new (); - - /* Add neighbors to the list. */ - for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr)) - { - /* neighbor declared to be DR. */ - if (NBR_IS_DR (nbr)) - listnode_add (dr_list, nbr); - - /* Preserve neighbor BDR. */ - if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) - bdr = nbr; - } - - /* Elect Designated Router. */ - if (listcount (dr_list) > 0) - dr = ospf_dr_election_sub (dr_list); - else - dr = bdr; - - /* Set DR to interface. */ - if (dr) - DR (oi) = dr->address.u.prefix4; - else - DR (oi).s_addr = 0; - - list_delete (dr_list); - - return dr; + struct list *dr_list; + struct listnode *node; + struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL; + + dr_list = list_new(); + + /* Add neighbors to the list. */ + for (ALL_LIST_ELEMENTS_RO(el_list, node, nbr)) { + /* neighbor declared to be DR. */ + if (NBR_IS_DR(nbr)) + listnode_add(dr_list, nbr); + + /* Preserve neighbor BDR. */ + if (IPV4_ADDR_SAME(&BDR(oi), &nbr->address.u.prefix4)) + bdr = nbr; + } + + /* Elect Designated Router. */ + if (listcount(dr_list) > 0) + dr = ospf_dr_election_sub(dr_list); + else + dr = bdr; + + /* Set DR to interface. */ + if (dr) + DR(oi) = dr->address.u.prefix4; + else + DR(oi).s_addr = 0; + + list_delete(&dr_list); + + return dr; } -static struct ospf_neighbor * -ospf_elect_bdr (struct ospf_interface *oi, struct list *el_list) +static struct ospf_neighbor *ospf_elect_bdr(struct ospf_interface *oi, + struct list *el_list) { - struct list *bdr_list, *no_dr_list; - struct listnode *node; - struct ospf_neighbor *nbr, *bdr = NULL; - - bdr_list = list_new (); - no_dr_list = list_new (); - - /* Add neighbors to the list. */ - for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr)) - { - /* neighbor declared to be DR. */ - if (NBR_IS_DR (nbr)) - continue; - - /* neighbor declared to be BDR. */ - if (NBR_IS_BDR (nbr)) - listnode_add (bdr_list, nbr); - - listnode_add (no_dr_list, nbr); - } - - /* Elect Backup Designated Router. */ - if (listcount (bdr_list) > 0) - bdr = ospf_dr_election_sub (bdr_list); - else - bdr = ospf_dr_election_sub (no_dr_list); - - /* Set BDR to interface. */ - if (bdr) - BDR (oi) = bdr->address.u.prefix4; - else - BDR (oi).s_addr = 0; - - list_delete (bdr_list); - list_delete (no_dr_list); - - return bdr; + struct list *bdr_list, *no_dr_list; + struct listnode *node; + struct ospf_neighbor *nbr, *bdr = NULL; + + bdr_list = list_new(); + no_dr_list = list_new(); + + /* Add neighbors to the list. */ + for (ALL_LIST_ELEMENTS_RO(el_list, node, nbr)) { + /* neighbor declared to be DR. */ + if (NBR_IS_DR(nbr)) + continue; + + /* neighbor declared to be BDR. */ + if (NBR_IS_BDR(nbr)) + listnode_add(bdr_list, nbr); + + listnode_add(no_dr_list, nbr); + } + + /* Elect Backup Designated Router. */ + if (listcount(bdr_list) > 0) + bdr = ospf_dr_election_sub(bdr_list); + else + bdr = ospf_dr_election_sub(no_dr_list); + + /* Set BDR to interface. */ + if (bdr) + BDR(oi) = bdr->address.u.prefix4; + else + BDR(oi).s_addr = 0; + + list_delete(&bdr_list); + list_delete(&no_dr_list); + + return bdr; } -static int -ospf_ism_state (struct ospf_interface *oi) +static int ospf_ism_state(struct ospf_interface *oi) { - if (IPV4_ADDR_SAME (&DR (oi), &oi->address->u.prefix4)) - return ISM_DR; - else if (IPV4_ADDR_SAME (&BDR (oi), &oi->address->u.prefix4)) - return ISM_Backup; - else - return ISM_DROther; + if (IPV4_ADDR_SAME(&DR(oi), &oi->address->u.prefix4)) + return ISM_DR; + else if (IPV4_ADDR_SAME(&BDR(oi), &oi->address->u.prefix4)) + return ISM_Backup; + else + return ISM_DROther; } -static void -ospf_dr_eligible_routers (struct route_table *nbrs, struct list *el_list) +static void ospf_dr_eligible_routers(struct route_table *nbrs, + struct list *el_list) { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor eligible? */ - if (nbr->priority > 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - listnode_add (el_list, nbr); + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor eligible? */ + if (nbr->priority > 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + listnode_add(el_list, nbr); } /* Generate AdjOK? NSM event. */ -static void -ospf_dr_change (struct ospf *ospf, struct route_table *nbrs) +static void ospf_dr_change(struct ospf *ospf, struct route_table *nbrs) { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME(&nbr->router_id, + &ospf->router_id)) + OSPF_NSM_EVENT_SCHEDULE( + nbr, NSM_AdjOK); } -static int -ospf_dr_election (struct ospf_interface *oi) +static int ospf_dr_election(struct ospf_interface *oi) { - struct in_addr old_dr, old_bdr; - int old_state, new_state; - struct list *el_list; + struct in_addr old_dr, old_bdr; + int old_state, new_state; + struct list *el_list; - /* backup current values. */ - old_dr = DR (oi); - old_bdr = BDR (oi); - old_state = oi->state; + /* backup current values. */ + old_dr = DR(oi); + old_bdr = BDR(oi); + old_state = oi->state; - el_list = list_new (); + el_list = list_new(); - /* List eligible routers. */ - ospf_dr_eligible_routers (oi->nbrs, el_list); + /* List eligible routers. */ + ospf_dr_eligible_routers(oi->nbrs, el_list); - /* First election of DR and BDR. */ - ospf_elect_bdr (oi, el_list); - ospf_elect_dr (oi, el_list); + /* First election of DR and BDR. */ + ospf_elect_bdr(oi, el_list); + ospf_elect_dr(oi, el_list); - new_state = ospf_ism_state (oi); + new_state = ospf_ism_state(oi); - zlog_debug ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi))); - zlog_debug ("DR-Election[1st]: DR %s", inet_ntoa (DR (oi))); + zlog_debug("DR-Election[1st]: Backup %s", inet_ntoa(BDR(oi))); + zlog_debug("DR-Election[1st]: DR %s", inet_ntoa(DR(oi))); - if (new_state != old_state && - !(new_state == ISM_DROther && old_state < ISM_DROther)) - { - ospf_elect_bdr (oi, el_list); - ospf_elect_dr (oi, el_list); + if (new_state != old_state + && !(new_state == ISM_DROther && old_state < ISM_DROther)) { + ospf_elect_bdr(oi, el_list); + ospf_elect_dr(oi, el_list); - new_state = ospf_ism_state (oi); + new_state = ospf_ism_state(oi); - zlog_debug ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi))); - zlog_debug ("DR-Election[2nd]: DR %s", inet_ntoa (DR (oi))); - } + zlog_debug("DR-Election[2nd]: Backup %s", inet_ntoa(BDR(oi))); + zlog_debug("DR-Election[2nd]: DR %s", inet_ntoa(DR(oi))); + } - list_delete (el_list); + list_delete(&el_list); - /* if DR or BDR changes, cause AdjOK? neighbor event. */ - if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) || - !IPV4_ADDR_SAME (&old_bdr, &BDR (oi))) - ospf_dr_change (oi->ospf, oi->nbrs); + /* if DR or BDR changes, cause AdjOK? neighbor event. */ + if (!IPV4_ADDR_SAME(&old_dr, &DR(oi)) + || !IPV4_ADDR_SAME(&old_bdr, &BDR(oi))) + ospf_dr_change(oi->ospf, oi->nbrs); - return new_state; + return new_state; } -int -ospf_hello_timer (struct thread *thread) +int ospf_hello_timer(struct thread *thread) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - oi->t_hello = NULL; + oi = THREAD_ARG(thread); + oi->t_hello = NULL; - if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) - zlog_debug("ISM[%s]: Timer (Hello timer expire)", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_TIMERS)) + zlog_debug("ISM[%s]: Timer (Hello timer expire)", IF_NAME(oi)); - /* Sending hello packet. */ - ospf_hello_send (oi); + /* Sending hello packet. */ + ospf_hello_send(oi); - /* Hello timer set. */ - OSPF_HELLO_TIMER_ON (oi); - - return 0; + /* Hello timer set. */ + OSPF_HELLO_TIMER_ON(oi); + + return 0; } -static int -ospf_wait_timer (struct thread *thread) +static int ospf_wait_timer(struct thread *thread) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - oi->t_wait = NULL; + oi = THREAD_ARG(thread); + oi->t_wait = NULL; - if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) - zlog_debug("ISM[%s]: Timer (Wait timer expire)", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_TIMERS)) + zlog_debug("ISM[%s]: Timer (Wait timer expire)", IF_NAME(oi)); - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_WaitTimer); - return 0; + return 0; } -/* Hook function called after ospf ISM event is occured. And vty's +/* Hook function called after ospf ISM event is occurred. And vty's network command invoke this function after making interface structure. */ -static void -ism_timer_set (struct ospf_interface *oi) +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; - } + 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; + } } -static int -ism_interface_up (struct ospf_interface *oi) +static int ism_interface_up(struct ospf_interface *oi) { - int next_state = 0; - - /* if network type is point-to-point, Point-to-MultiPoint or virtual link, - the state transitions to Point-to-Point. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT || - oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || - oi->type == OSPF_IFTYPE_VIRTUALLINK) - next_state = ISM_PointToPoint; - /* Else if the router is not eligible to DR, the state transitions to - DROther. */ - else if (PRIORITY (oi) == 0) /* router is eligible? */ - next_state = ISM_DROther; - else - /* Otherwise, the state transitions to Waiting. */ - next_state = ISM_Waiting; - - if (oi->type == OSPF_IFTYPE_NBMA) - ospf_nbr_nbma_if_update (oi->ospf, oi); - - /* ospf_ism_event (t); */ - return next_state; + int next_state = 0; + + /* if network type is point-to-point, Point-to-MultiPoint or virtual + link, + the state transitions to Point-to-Point. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + next_state = ISM_PointToPoint; + /* Else if the router is not eligible to DR, the state transitions to + DROther. */ + else if (PRIORITY(oi) == 0) /* router is eligible? */ + next_state = ISM_DROther; + else + /* Otherwise, the state transitions to Waiting. */ + next_state = ISM_Waiting; + + if (oi->type == OSPF_IFTYPE_NBMA) + ospf_nbr_nbma_if_update(oi->ospf, oi); + + /* ospf_ism_event (t); */ + return next_state; } -static int -ism_loop_ind (struct ospf_interface *oi) +static int ism_loop_ind(struct ospf_interface *oi) { - int ret = 0; - - /* call ism_interface_down. */ - /* ret = ism_interface_down (oi); */ + /* call ism_interface_down. */ + /* ret = ism_interface_down (oi); */ - return ret; + return 0; } /* Interface down event handler. */ -static int -ism_interface_down (struct ospf_interface *oi) +static int ism_interface_down(struct ospf_interface *oi) { - ospf_if_cleanup (oi); - return 0; + ospf_if_cleanup(oi); + return 0; } -static int -ism_backup_seen (struct ospf_interface *oi) +static int ism_backup_seen(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_wait_timer (struct ospf_interface *oi) +static int ism_wait_timer(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_neighbor_change (struct ospf_interface *oi) +static int ism_neighbor_change(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_ignore (struct ospf_interface *oi) +static int ism_ignore(struct ospf_interface *oi) { - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug("ISM[%s]: ism_ignore called", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: ism_ignore called", IF_NAME(oi)); - return 0; + return 0; } /* Interface State Machine */ -struct { - int (*func) (struct ospf_interface *); - int next_state; -} ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] = -{ - { - /* DependUpon: dummy state. */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DependUpon }, /* InterfaceUp */ - { ism_ignore, ISM_DependUpon }, /* WaitTimer */ - { ism_ignore, ISM_DependUpon }, /* BackupSeen */ - { ism_ignore, ISM_DependUpon }, /* NeighborChange */ - { ism_ignore, ISM_DependUpon }, /* LoopInd */ - { ism_ignore, ISM_DependUpon }, /* UnloopInd */ - { ism_ignore, ISM_DependUpon }, /* InterfaceDown */ - }, - { - /* Down:*/ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_interface_up, ISM_DependUpon }, /* InterfaceUp */ - { ism_ignore, ISM_Down }, /* WaitTimer */ - { ism_ignore, ISM_Down }, /* BackupSeen */ - { ism_ignore, ISM_Down }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Down }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Loopback: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Loopback }, /* InterfaceUp */ - { ism_ignore, ISM_Loopback }, /* WaitTimer */ - { ism_ignore, ISM_Loopback }, /* BackupSeen */ - { ism_ignore, ISM_Loopback }, /* NeighborChange */ - { ism_ignore, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Down }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Waiting: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Waiting }, /* InterfaceUp */ - { ism_wait_timer, ISM_DependUpon }, /* WaitTimer */ - { ism_backup_seen, ISM_DependUpon }, /* BackupSeen */ - { ism_ignore, ISM_Waiting }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Waiting }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Point-to-Point: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_PointToPoint }, /* InterfaceUp */ - { ism_ignore, ISM_PointToPoint }, /* WaitTimer */ - { ism_ignore, ISM_PointToPoint }, /* BackupSeen */ - { ism_ignore, ISM_PointToPoint }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_PointToPoint }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* DROther: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DROther }, /* InterfaceUp */ - { ism_ignore, ISM_DROther }, /* WaitTimer */ - { ism_ignore, ISM_DROther }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_DROther }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Backup: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Backup }, /* InterfaceUp */ - { ism_ignore, ISM_Backup }, /* WaitTimer */ - { ism_ignore, ISM_Backup }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Backup }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* DR: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DR }, /* InterfaceUp */ - { ism_ignore, ISM_DR }, /* WaitTimer */ - { ism_ignore, ISM_DR }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_DR }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, -}; - -static const char *ospf_ism_event_str[] = -{ - "NoEvent", - "InterfaceUp", - "WaitTimer", - "BackupSeen", - "NeighborChange", - "LoopInd", - "UnLoopInd", - "InterfaceDown", +const struct { + int (*func)(struct ospf_interface *); + int next_state; +} ISM[OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] = { + { + /* DependUpon: dummy state. */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DependUpon}, /* InterfaceUp */ + {ism_ignore, ISM_DependUpon}, /* WaitTimer */ + {ism_ignore, ISM_DependUpon}, /* BackupSeen */ + {ism_ignore, ISM_DependUpon}, /* NeighborChange */ + {ism_ignore, ISM_DependUpon}, /* LoopInd */ + {ism_ignore, ISM_DependUpon}, /* UnloopInd */ + {ism_ignore, ISM_DependUpon}, /* InterfaceDown */ + }, + { + /* Down:*/ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_interface_up, ISM_DependUpon}, /* InterfaceUp */ + {ism_ignore, ISM_Down}, /* WaitTimer */ + {ism_ignore, ISM_Down}, /* BackupSeen */ + {ism_ignore, ISM_Down}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Down}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Loopback: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Loopback}, /* InterfaceUp */ + {ism_ignore, ISM_Loopback}, /* WaitTimer */ + {ism_ignore, ISM_Loopback}, /* BackupSeen */ + {ism_ignore, ISM_Loopback}, /* NeighborChange */ + {ism_ignore, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Down}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Waiting: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Waiting}, /* InterfaceUp */ + {ism_wait_timer, ISM_DependUpon}, /* WaitTimer */ + {ism_backup_seen, ISM_DependUpon}, /* BackupSeen */ + {ism_ignore, ISM_Waiting}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Waiting}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Point-to-Point: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_PointToPoint}, /* InterfaceUp */ + {ism_ignore, ISM_PointToPoint}, /* WaitTimer */ + {ism_ignore, ISM_PointToPoint}, /* BackupSeen */ + {ism_ignore, ISM_PointToPoint}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_PointToPoint}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* DROther: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DROther}, /* InterfaceUp */ + {ism_ignore, ISM_DROther}, /* WaitTimer */ + {ism_ignore, ISM_DROther}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_DROther}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Backup: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Backup}, /* InterfaceUp */ + {ism_ignore, ISM_Backup}, /* WaitTimer */ + {ism_ignore, ISM_Backup}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Backup}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* DR: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DR}, /* InterfaceUp */ + {ism_ignore, ISM_DR}, /* WaitTimer */ + {ism_ignore, ISM_DR}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_DR}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, +}; + +static const char *const ospf_ism_event_str[] = { + "NoEvent", "InterfaceUp", "WaitTimer", "BackupSeen", + "NeighborChange", "LoopInd", "UnLoopInd", "InterfaceDown", }; -static void -ism_change_state (struct ospf_interface *oi, int state) +static void ism_change_state(struct ospf_interface *oi, int state) { - int old_state; - struct ospf_lsa *lsa; - - /* Logging change of state. */ - if (IS_DEBUG_OSPF (ism, ISM_STATUS)) - zlog_debug("ISM[%s]: State change %s -> %s", IF_NAME(oi), - lookup_msg(ospf_ism_state_msg, oi->state, NULL), - lookup_msg(ospf_ism_state_msg, state, NULL)); - - old_state = oi->state; - oi->state = state; - oi->state_change++; - - hook_call(ospf_ism_change, oi, state, old_state); - - /* Set multicast memberships appropriately for new state. */ - ospf_if_set_multicast(oi); - - if (old_state == ISM_Down || state == ISM_Down) - ospf_check_abr_status (oi->ospf); - - /* Originate router-LSA. */ - if (state == ISM_Down) - { - if (oi->area->act_ints > 0) - oi->area->act_ints--; - } - else if (old_state == ISM_Down) - oi->area->act_ints++; - - /* schedule router-LSA originate. */ - ospf_router_lsa_update_area (oi->area); - - /* Originate network-LSA. */ - if (old_state != ISM_DR && state == ISM_DR) - ospf_network_lsa_update (oi); - else if (old_state == ISM_DR && state != ISM_DR) - { - /* Free self originated network LSA. */ - lsa = oi->network_lsa_self; - if (lsa) - ospf_lsa_flush_area (lsa, oi->area); - - ospf_lsa_unlock (&oi->network_lsa_self); - oi->network_lsa_self = NULL; - } - - ospf_opaque_ism_change (oi, old_state); - - /* Check area border status. */ - ospf_check_abr_status (oi->ospf); + int old_state; + struct ospf_lsa *lsa; + + /* Logging change of state. */ + if (IS_DEBUG_OSPF(ism, ISM_STATUS)) + zlog_debug("ISM[%s]: State change %s -> %s", IF_NAME(oi), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + lookup_msg(ospf_ism_state_msg, state, NULL)); + + old_state = oi->state; + oi->state = state; + oi->state_change++; + + hook_call(ospf_ism_change, oi, state, old_state); + + /* Set multicast memberships appropriately for new state. */ + ospf_if_set_multicast(oi); + + if (old_state == ISM_Down || state == ISM_Down) + ospf_check_abr_status(oi->ospf); + + /* Originate router-LSA. */ + if (state == ISM_Down) { + if (oi->area->act_ints > 0) + oi->area->act_ints--; + } else if (old_state == ISM_Down) + oi->area->act_ints++; + + /* schedule router-LSA originate. */ + ospf_router_lsa_update_area(oi->area); + + /* Originate network-LSA. */ + if (old_state != ISM_DR && state == ISM_DR) + ospf_network_lsa_update(oi); + else if (old_state == ISM_DR && state != ISM_DR) { + /* Free self originated network LSA. */ + lsa = oi->network_lsa_self; + if (lsa) + ospf_lsa_flush_area(lsa, oi->area); + + ospf_lsa_unlock(&oi->network_lsa_self); + oi->network_lsa_self = NULL; + } + + ospf_opaque_ism_change(oi, old_state); + + /* Check area border status. */ + ospf_check_abr_status(oi->ospf); } /* Execute ISM event process. */ -int -ospf_ism_event (struct thread *thread) +int ospf_ism_event(struct thread *thread) { - int event; - int next_state; - struct ospf_interface *oi; + int event; + int next_state; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - event = THREAD_VAL (thread); + oi = THREAD_ARG(thread); + event = THREAD_VAL(thread); - /* Call function. */ - next_state = (*(ISM [oi->state][event].func))(oi); + /* Call function. */ + next_state = (*(ISM[oi->state][event].func))(oi); - if (! next_state) - next_state = ISM [oi->state][event].next_state; + if (!next_state) + next_state = ISM[oi->state][event].next_state; - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug("ISM[%s]: %s (%s)", IF_NAME(oi), - lookup_msg(ospf_ism_state_msg, oi->state, NULL), - ospf_ism_event_str[event]); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: %s (%s)", IF_NAME(oi), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + ospf_ism_event_str[event]); - /* If state is changed. */ - if (next_state != oi->state) - ism_change_state (oi, next_state); + /* If state is changed. */ + if (next_state != oi->state) + ism_change_state(oi, next_state); - /* Make sure timer is set. */ - ism_timer_set (oi); + /* Make sure timer is set. */ + ism_timer_set(oi); - return 0; + return 0; } -