diff options
author | paul <paul> | 2002-12-13 20:15:29 +0000 |
---|---|---|
committer | paul <paul> | 2002-12-13 20:15:29 +0000 |
commit | 718e3744195351130f4ce7dbe0613f4b3e23df93 (patch) | |
tree | bac2ad39971cd43f31241ef123bd4e470f695ac9 /ospf6d/ospf6_nsm.c |
Initial revision
Diffstat (limited to 'ospf6d/ospf6_nsm.c')
-rw-r--r-- | ospf6d/ospf6_nsm.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/ospf6d/ospf6_nsm.c b/ospf6d/ospf6_nsm.c new file mode 100644 index 00000000..aa08d40b --- /dev/null +++ b/ospf6d/ospf6_nsm.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 1999 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ospf6d.h" + +static int +nbs_full_change (struct ospf6_interface *ospf6_interface) +{ + CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, ospf6_interface); + return 0; +} + +static int +nbs_change (state_t nbs_next, char *reason, struct ospf6_neighbor *o6n) +{ + state_t nbs_previous; + + nbs_previous = o6n->state; + o6n->state = nbs_next; + + if (nbs_previous == nbs_next) + return 0; + + /* statistics */ + o6n->ospf6_stat_state_changed++; + gettimeofday (&o6n->last_changed, NULL); + + /* log */ + if (IS_OSPF6_DUMP_NEIGHBOR) + { + if (reason) + zlog_info ("Neighbor status change %s: [%s]->[%s](%s)", + o6n->str, + ospf6_neighbor_state_string[nbs_previous], + ospf6_neighbor_state_string[nbs_next], + reason); + else + zlog_info ("Neighbor status change %s: [%s]->[%s]", + o6n->str, + ospf6_neighbor_state_string[nbs_previous], + ospf6_neighbor_state_string[nbs_next]); + } + + if (nbs_previous == NBS_FULL || nbs_next == NBS_FULL) + nbs_full_change (o6n->ospf6_interface); + + /* check for LSAs that already reached MaxAge */ + if ((nbs_previous == NBS_EXCHANGE || nbs_previous == NBS_LOADING) && + (nbs_next != NBS_EXCHANGE && nbs_next != NBS_LOADING)) + { + ospf6_maxage_remover (); + } + + CALL_CHANGE_HOOK (&neighbor_hook, o6n); + + return 0; +} + +/* RFC2328 section 10.4 */ +int +need_adjacency (struct ospf6_neighbor *o6n) +{ + + if (o6n->ospf6_interface->state == IFS_PTOP) + return 1; + if (o6n->ospf6_interface->state == IFS_DR) + return 1; + if (o6n->ospf6_interface->state == IFS_BDR) + return 1; + if (o6n->router_id == o6n->ospf6_interface->dr) + return 1; + if (o6n->router_id == o6n->ospf6_interface->bdr) + return 1; + + return 0; +} + +int +hello_received (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *HelloReceived*", o6n->str); + + if (o6n->inactivity_timer) + thread_cancel (o6n->inactivity_timer); + + o6n->inactivity_timer = thread_add_timer (master, inactivity_timer, o6n, + o6n->ospf6_interface->dead_interval); + if (o6n->state <= NBS_DOWN) + nbs_change (NBS_INIT, "HelloReceived", o6n); + return 0; +} + +int +twoway_received (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state > NBS_INIT) + return 0; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *2Way-Received*", o6n->str); + + thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0); + + if (!need_adjacency (o6n)) + { + nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n); + return 0; + } + else + nbs_change (NBS_EXSTART, "Need Adjacency", o6n); + + DD_MSBIT_SET (o6n->dbdesc_bits); + DD_MBIT_SET (o6n->dbdesc_bits); + DD_IBIT_SET (o6n->dbdesc_bits); + + if (o6n->thread_send_dbdesc) + thread_cancel (o6n->thread_send_dbdesc); + o6n->thread_send_dbdesc = + thread_add_event (master, ospf6_send_dbdesc, o6n, 0); + if (o6n->thread_rxmt_dbdesc) + thread_cancel (o6n->thread_rxmt_dbdesc); + o6n->thread_rxmt_dbdesc = (struct thread *) NULL; + + return 0; +} + +int +negotiation_done (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state != NBS_EXSTART) + return 0; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *NegotiationDone*", o6n->str); + + nbs_change (NBS_EXCHANGE, "NegotiationDone", o6n); + DD_IBIT_CLEAR (o6n->dbdesc_bits); + + return 0; +} + +int +exchange_done (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state != NBS_EXCHANGE) + return 0; + + if (o6n->thread_rxmt_dbdesc) + thread_cancel (o6n->thread_rxmt_dbdesc); + o6n->thread_rxmt_dbdesc = (struct thread *) NULL; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *ExchangeDone*", o6n->str); + + ospf6_lsdb_remove_all (o6n->dbdesc_list); + + thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, o6n, + o6n->ospf6_interface->dead_interval); + + if (o6n->request_list->count == 0) + nbs_change (NBS_FULL, "Requestlist Empty", o6n); + else + { + thread_add_event (master, ospf6_send_lsreq, o6n, 0); + nbs_change (NBS_LOADING, "Requestlist Not Empty", o6n); + } + return 0; +} + +int +loading_done (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state != NBS_LOADING) + return 0; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *LoadingDone*", o6n->str); + + assert (o6n->request_list->count == 0); + + nbs_change (NBS_FULL, "LoadingDone", o6n); + + return 0; +} + +int +adj_ok (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *AdjOK?*", o6n->str); + + if (o6n->state == NBS_TWOWAY) + { + if (!need_adjacency (o6n)) + { + nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n); + return 0; + } + else + nbs_change (NBS_EXSTART, "Need Adjacency", o6n); + + DD_MSBIT_SET (o6n->dbdesc_bits); + DD_MBIT_SET (o6n->dbdesc_bits); + DD_IBIT_SET (o6n->dbdesc_bits); + + if (o6n->thread_send_dbdesc) + thread_cancel (o6n->thread_send_dbdesc); + o6n->thread_send_dbdesc = + thread_add_event (master, ospf6_send_dbdesc, o6n, 0); + + return 0; + } + + if (o6n->state >= NBS_EXSTART) + { + if (need_adjacency (o6n)) + return 0; + else + { + nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n); + ospf6_neighbor_lslist_clear (o6n); + } + } + return 0; +} + +int +seqnumber_mismatch (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state < NBS_EXCHANGE) + return 0; + + /* statistics */ + o6n->ospf6_stat_seqnum_mismatch++; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *SeqNumberMismatch*", o6n->str); + + nbs_change (NBS_EXSTART, "SeqNumberMismatch", o6n); + + DD_MSBIT_SET (o6n->dbdesc_bits); + DD_MBIT_SET (o6n->dbdesc_bits); + DD_IBIT_SET (o6n->dbdesc_bits); + ospf6_neighbor_lslist_clear (o6n); + + if (o6n->thread_send_dbdesc) + thread_cancel (o6n->thread_send_dbdesc); + o6n->thread_send_dbdesc = + thread_add_event (master, ospf6_send_dbdesc, o6n, 0); + + return 0; +} + +int +bad_lsreq (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state < NBS_EXCHANGE) + return 0; + + /* statistics */ + o6n->ospf6_stat_bad_lsreq++; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *BadLSReq*", o6n->str); + + nbs_change (NBS_EXSTART, "BadLSReq", o6n); + + DD_MSBIT_SET (o6n->dbdesc_bits); + DD_MBIT_SET (o6n->dbdesc_bits); + DD_IBIT_SET (o6n->dbdesc_bits); + ospf6_neighbor_lslist_clear (o6n); + + if (o6n->thread_send_dbdesc) + thread_cancel (o6n->thread_send_dbdesc); + o6n->thread_send_dbdesc = + thread_add_event (master, ospf6_send_dbdesc, o6n, 0); + + return 0; +} + +int +oneway_received (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + if (o6n->state < NBS_TWOWAY) + return 0; + + /* statistics */ + o6n->ospf6_stat_oneway_received++; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *1Way-Received*", o6n->str); + + nbs_change (NBS_INIT, "1Way-Received", o6n); + + thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0); + + ospf6_neighbor_thread_cancel_all (o6n); + ospf6_neighbor_lslist_clear (o6n); + return 0; +} + +int +inactivity_timer (struct thread *thread) +{ + struct ospf6_neighbor *o6n; + + o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (o6n); + + /* statistics */ + o6n->ospf6_stat_inactivity_timer++; + + if (IS_OSPF6_DUMP_NEIGHBOR) + zlog_info ("Neighbor Event %s: *InactivityTimer*", o6n->str); + + o6n->inactivity_timer = NULL; + o6n->dr = o6n->bdr = o6n->prevdr = o6n->prevbdr = 0; + nbs_change (NBS_DOWN, "InactivityTimer", o6n); + + thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0); + + listnode_delete (o6n->ospf6_interface->neighbor_list, o6n); + ospf6_neighbor_delete (o6n); + + return 0; +} + |