diff options
Diffstat (limited to 'isisd/isis_csm.c')
-rw-r--r-- | isisd/isis_csm.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c new file mode 100644 index 0000000..9e278d4 --- /dev/null +++ b/isisd/isis_csm.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * IS-IS Rout(e)ing protocol - isis_csm.c + * IS-IS circuit state machine + * Copyright (C) 2001,2002 Sampo Saaristo + * Tampere University of Technology + * Institute of Communications Engineering + */ + +#include <zebra.h> + +#include "log.h" +#include "memory.h" +#include "if.h" +#include "linklist.h" +#include "command.h" +#include "frrevent.h" +#include "hash.h" +#include "prefix.h" +#include "stream.h" + +#include "isisd/isis_constants.h" +#include "isisd/isis_common.h" +#include "isisd/isis_flags.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_pdu.h" +#include "isisd/isis_network.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_dr.h" +#include "isisd/isisd.h" +#include "isisd/isis_csm.h" +#include "isisd/isis_events.h" +#include "isisd/isis_errors.h" + +static const char *const csm_statestr[] = {"C_STATE_NA", "C_STATE_INIT", + "C_STATE_CONF", "C_STATE_UP"}; + +#define STATE2STR(S) csm_statestr[S] + +static const char *const csm_eventstr[] = { + "NO_STATE", "ISIS_ENABLE", "IF_UP_FROM_Z", + "ISIS_DISABLE", "IF_DOWN_FROM_Z", +}; + +#define EVENT2STR(E) csm_eventstr[E] + +struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, + struct isis_circuit *circuit, + void *arg) +{ + enum isis_circuit_state old_state; + struct isis_area *area = NULL; + struct interface *ifp; + + assert(circuit); + + old_state = circuit->state; + if (IS_DEBUG_EVENTS) + zlog_debug("CSM_EVENT for %s: %s", circuit->interface->name, + EVENT2STR(event)); + + switch (old_state) { + case C_STATE_NA: + switch (event) { + case ISIS_ENABLE: + area = arg; + + isis_circuit_configure(circuit, area); + circuit->state = C_STATE_CONF; + break; + case IF_UP_FROM_Z: + ifp = arg; + + isis_circuit_if_add(circuit, ifp); + circuit->state = C_STATE_INIT; + break; + case ISIS_DISABLE: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already disabled", + circuit->interface->name); + break; + case IF_DOWN_FROM_Z: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already disconnected", + circuit->interface->name); + break; + } + break; + case C_STATE_INIT: + switch (event) { + case ISIS_ENABLE: + area = arg; + + isis_circuit_configure(circuit, area); + if (isis_circuit_up(circuit) != ISIS_OK) { + isis_circuit_deconfigure(circuit, area); + break; + } + circuit->state = C_STATE_UP; + isis_event_circuit_state_change(circuit, circuit->area, + 1); + break; + case IF_UP_FROM_Z: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already connected", + circuit->interface->name); + break; + case ISIS_DISABLE: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already disabled", + circuit->interface->name); + break; + case IF_DOWN_FROM_Z: + ifp = arg; + + isis_circuit_if_del(circuit, ifp); + circuit->state = C_STATE_NA; + break; + } + break; + case C_STATE_CONF: + switch (event) { + case ISIS_ENABLE: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s is already enabled", + circuit->interface->name); + break; + case IF_UP_FROM_Z: + ifp = arg; + + isis_circuit_if_add(circuit, ifp); + if (isis_circuit_up(circuit) != ISIS_OK) { + isis_circuit_if_del(circuit, ifp); + flog_err( + EC_ISIS_CONFIG, + "Could not bring up %s because of invalid config.", + circuit->interface->name); + break; + } + circuit->state = C_STATE_UP; + isis_event_circuit_state_change(circuit, circuit->area, + 1); + break; + case ISIS_DISABLE: + area = arg; + + isis_circuit_deconfigure(circuit, area); + circuit->state = C_STATE_NA; + break; + case IF_DOWN_FROM_Z: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already disconnected", + circuit->interface->name); + break; + } + break; + case C_STATE_UP: + switch (event) { + case ISIS_ENABLE: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already enabled", + circuit->interface->name); + break; + case IF_UP_FROM_Z: + if (IS_DEBUG_EVENTS) + zlog_debug("circuit %s already connected", + circuit->interface->name); + break; + case ISIS_DISABLE: + area = arg; + + isis_circuit_down(circuit); + isis_circuit_deconfigure(circuit, area); + circuit->state = C_STATE_INIT; + isis_event_circuit_state_change(circuit, area, 0); + break; + case IF_DOWN_FROM_Z: + ifp = arg; + + isis_circuit_down(circuit); + isis_circuit_if_del(circuit, ifp); + circuit->state = C_STATE_CONF; + isis_event_circuit_state_change(circuit, circuit->area, + 0); + break; + } + break; + } + + if (IS_DEBUG_EVENTS) + zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state), + STATE2STR(circuit->state)); + + return circuit; +} |