roletrns.c
上传用户:allwinjm
上传日期:2021-08-29
资源大小:99k
文件大小:12k
- /************************************************************************
- * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
- * Copyright (C) 2001-2003 Optical Access
- * Author: Alex Rozin
- *
- * This file is part of RSTP library.
- *
- * RSTP library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; version 2.1
- *
- * RSTP library 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 Lesser
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with RSTP library; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- **********************************************************************/
- /* Port Role Transitions state machine : 17.24 */
-
- #include "base.h"
- #include "stpm.h"
- #define STATES {
- CHOOSE(INIT_PORT),
- CHOOSE(BLOCK_PORT),
- CHOOSE(BLOCKED_PORT),
- CHOOSE(BACKUP_PORT),
- CHOOSE(ROOT_PROPOSED),
- CHOOSE(ROOT_AGREED),
- CHOOSE(REROOT),
- CHOOSE(ROOT_PORT),
- CHOOSE(REROOTED),
- CHOOSE(ROOT_LEARN),
- CHOOSE(ROOT_FORWARD),
- CHOOSE(DESIGNATED_PROPOSE),
- CHOOSE(DESIGNATED_SYNCED),
- CHOOSE(DESIGNATED_RETIRED),
- CHOOSE(DESIGNATED_PORT),
- CHOOSE(DESIGNATED_LISTEN),
- CHOOSE(DESIGNATED_LEARN),
- CHOOSE(DESIGNATED_FORWARD),
- }
- #define GET_STATE_NAME STP_roletrns_get_state_name
- #include "choose.h"
- static void
- setSyncBridge (STATE_MACH_T *this)
- {
- register PORT_T* port;
- for (port = this->owner.port->owner->ports; port; port = port->next) {
- port->sync = True; /* in ROOT_PROPOSED (setSyncBridge) */
- }
- }
- static void
- setReRootBridge (STATE_MACH_T *this)
- {
- register PORT_T* port;
- for (port = this->owner.port->owner->ports; port; port = port->next) {
- port->reRoot = True; /* In setReRootBridge */
- }
- }
- static Bool
- compute_all_synced (PORT_T* this)
- {
- register PORT_T* port;
- for (port = this->owner->ports; port; port = port->next) {
- if (port->port_index == this->port_index) continue;
- if (! port->synced) {
- return False;
- }
- }
- return True;
- }
- static Bool
- compute_re_rooted (PORT_T* this)
- {
- register PORT_T* port;
- for (port = this->owner->ports; port; port = port->next) {
- if (port->port_index == this->port_index) continue;
- if (port->rrWhile) {
- return False;
- }
- }
- return True;
- }
- void
- STP_roletrns_enter_state (STATE_MACH_T* this)
- {
- register PORT_T* port = this->owner.port;
- register STPM_T* stpm;
- stpm = port->owner;
- switch (this->State) {
- case BEGIN:
- case INIT_PORT:
- #if 0 /* due 802.1y Z.4 */
- port->role = DisabledPort;
- #else
- port->role = port->selectedRole = DisabledPort;
- port->reselect = True;
- #endif
- port->synced = False; /* in INIT */
- port->sync = True; /* in INIT */
- port->reRoot = True; /* in INIT_PORT */
- port->rrWhile = stpm->rootTimes.ForwardDelay;
- port->fdWhile = stpm->rootTimes.ForwardDelay;
- port->rbWhile = 0;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("after init", port);
- #endif
- break;
- case BLOCK_PORT:
- port->role = port->selectedRole;
- port->learn =
- port->forward = False;
- break;
- case BLOCKED_PORT:
- port->fdWhile = stpm->rootTimes.ForwardDelay;
- port->synced = True; /* In BLOCKED_PORT */
- port->rrWhile = 0;
- port->sync = port->reRoot = False; /* BLOCKED_PORT */
- break;
- case BACKUP_PORT:
- port->rbWhile = 2 * stpm->rootTimes.HelloTime;
- break;
- /* 17.23.2 */
- case ROOT_PROPOSED:
- setSyncBridge (this);
- port->proposed = False;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("ROOT_PROPOSED", port);
- #endif
- break;
- case ROOT_AGREED:
- port->proposed = port->sync = False; /* in ROOT_AGREED */
- port->synced = True; /* In ROOT_AGREED */
- port->newInfo = True;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("ROOT_AGREED", port);
- #endif
- break;
- case REROOT:
- setReRootBridge (this);
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("REROOT", port);
- #endif
- break;
- case ROOT_PORT:
- port->role = RootPort;
- port->rrWhile = stpm->rootTimes.ForwardDelay;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("ROOT_PORT", port);
- #endif
- break;
- case REROOTED:
- port->reRoot = False; /* In REROOTED */
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("REROOTED", port);
- #endif
- break;
- case ROOT_LEARN:
- port->fdWhile = stpm->rootTimes.ForwardDelay;
- port->learn = True;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("ROOT_LEARN", port);
- #endif
- break;
- case ROOT_FORWARD:
- port->fdWhile = 0;
- port->forward = True;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("ROOT_FORWARD", port);
- #endif
- break;
- /* 17.23.3 */
- case DESIGNATED_PROPOSE:
- port->proposing = True; /* in DESIGNATED_PROPOSE */
- port->newInfo = True;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_PROPOSE", port);
- #endif
- break;
- case DESIGNATED_SYNCED:
- port->rrWhile = 0;
- port->synced = True; /* DESIGNATED_SYNCED */
- port->sync = False; /* DESIGNATED_SYNCED */
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_SYNCED", port);
- #endif
- break;
- case DESIGNATED_RETIRED:
- port->reRoot = False; /* DESIGNATED_RETIRED */
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_RETIRED", port);
- #endif
- break;
- case DESIGNATED_PORT:
- port->role = DesignatedPort;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_PORT", port);
- #endif
- break;
- case DESIGNATED_LISTEN:
- port->learn = port->forward = False;
- port->fdWhile = stpm->rootTimes.ForwardDelay;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_LISTEN", port);
- #endif
- break;
- case DESIGNATED_LEARN:
- port->learn = True;
- port->fdWhile = stpm->rootTimes.ForwardDelay;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_LEARN", port);
- #endif
- break;
- case DESIGNATED_FORWARD:
- port->forward = True;
- port->fdWhile = 0;
- #ifdef STP_DBG
- if (this->debug)
- STP_port_trace_flags ("DESIGNATED_FORWARD", port);
- #endif
- break;
- };
- }
-
- Bool
- STP_roletrns_check_conditions (STATE_MACH_T* this)
- {
- register PORT_T *port = this->owner.port;
- register STPM_T *stpm;
- Bool allSynced;
- Bool allReRooted;
- stpm = port->owner;
- if (BEGIN == this->State) {
- return STP_hop_2_state (this, INIT_PORT);
- }
- if (port->role != port->selectedRole &&
- port->selected &&
- ! port->updtInfo) {
- switch (port->selectedRole) {
- case DisabledPort:
- case AlternatePort:
- case BackupPort:
- #if 0 /* def STP_DBG */
- if (this->debug) {
- stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
- (int) port->role, (int) port->selectedRole);
- }
- #endif
- return STP_hop_2_state (this, BLOCK_PORT);
- case RootPort:
- return STP_hop_2_state (this, ROOT_PORT);
- case DesignatedPort:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- default:
- return False;
- }
- }
- switch (this->State) {
- /* 17.23.1 */
- case INIT_PORT:
- return STP_hop_2_state (this, BLOCK_PORT);
- case BLOCK_PORT:
- if (!port->selected || port->updtInfo) break;
- if (!port->learning && !port->forwarding) {
- return STP_hop_2_state (this, BLOCKED_PORT);
- }
- break;
- case BLOCKED_PORT:
- if (!port->selected || port->updtInfo) break;
- if (port->fdWhile != stpm->rootTimes.ForwardDelay ||
- port->sync ||
- port->reRoot ||
- !port->synced) {
- return STP_hop_2_state (this, BLOCKED_PORT);
- }
- if (port->rbWhile != 2 * stpm->rootTimes.HelloTime &&
- port->role == BackupPort) {
- return STP_hop_2_state (this, BACKUP_PORT);
- }
- break;
- case BACKUP_PORT:
- return STP_hop_2_state (this, BLOCKED_PORT);
- /* 17.23.2 */
- case ROOT_PROPOSED:
- return STP_hop_2_state (this, ROOT_PORT);
- case ROOT_AGREED:
- return STP_hop_2_state (this, ROOT_PORT);
- case REROOT:
- return STP_hop_2_state (this, ROOT_PORT);
- case ROOT_PORT:
- if (!port->selected || port->updtInfo) break;
- if (!port->forward && !port->reRoot) {
- return STP_hop_2_state (this, REROOT);
- }
- allSynced = compute_all_synced (port);
- if ((port->proposed && allSynced) ||
- (!port->synced && allSynced)) {
- return STP_hop_2_state (this, ROOT_AGREED);
- }
- if (port->proposed && !port->synced) {
- return STP_hop_2_state (this, ROOT_PROPOSED);
- }
- allReRooted = compute_re_rooted (port);
- if ((!port->fdWhile ||
- ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
- port->learn && !port->forward) {
- return STP_hop_2_state (this, ROOT_FORWARD);
- }
- if ((!port->fdWhile ||
- ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
- !port->learn) {
- return STP_hop_2_state (this, ROOT_LEARN);
- }
- if (port->reRoot && port->forward) {
- return STP_hop_2_state (this, REROOTED);
- }
- if (port->rrWhile != stpm->rootTimes.ForwardDelay) {
- return STP_hop_2_state (this, ROOT_PORT);
- }
- break;
- case REROOTED:
- return STP_hop_2_state (this, ROOT_PORT);
- case ROOT_LEARN:
- return STP_hop_2_state (this, ROOT_PORT);
- case ROOT_FORWARD:
- return STP_hop_2_state (this, ROOT_PORT);
- /* 17.23.3 */
- case DESIGNATED_PROPOSE:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- case DESIGNATED_SYNCED:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- case DESIGNATED_RETIRED:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- case DESIGNATED_PORT:
- if (!port->selected || port->updtInfo) break;
- if (!port->forward && !port->agreed && !port->proposing && !port->operEdge) {
- return STP_hop_2_state (this, DESIGNATED_PROPOSE);
- }
- if (!port->rrWhile && port->reRoot) {
- return STP_hop_2_state (this, DESIGNATED_RETIRED);
- }
-
- if (!port->learning && !port->forwarding && !port->synced) {
- return STP_hop_2_state (this, DESIGNATED_SYNCED);
- }
- if (port->agreed && !port->synced) {
- return STP_hop_2_state (this, DESIGNATED_SYNCED);
- }
- if (port->operEdge && !port->synced) {
- return STP_hop_2_state (this, DESIGNATED_SYNCED);
- }
- if (port->sync && port->synced) {
- return STP_hop_2_state (this, DESIGNATED_SYNCED);
- }
- if ((!port->fdWhile || port->agreed || port->operEdge) &&
- (!port->rrWhile || !port->reRoot) &&
- !port->sync &&
- (port->learn && !port->forward)) {
- return STP_hop_2_state (this, DESIGNATED_FORWARD);
- }
- if ((!port->fdWhile || port->agreed || port->operEdge) &&
- (!port->rrWhile || !port->reRoot) &&
- !port->sync && !port->learn) {
- return STP_hop_2_state (this, DESIGNATED_LEARN);
- }
- if (((port->sync && !port->synced) ||
- (port->reRoot && port->rrWhile)) &&
- !port->operEdge && (port->learn || port->forward)) {
- return STP_hop_2_state (this, DESIGNATED_LISTEN);
- }
- break;
- case DESIGNATED_LISTEN:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- case DESIGNATED_LEARN:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- case DESIGNATED_FORWARD:
- return STP_hop_2_state (this, DESIGNATED_PORT);
- };
- return False;
- }