1 /************************************************************************ 2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 3 * Copyright (C) 2001-2003 Optical Access 4 * Author: Alex Rozin 5 * 6 * This file is part of RSTP library. 7 * 8 * RSTP library is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU Lesser General Public License as published by the 10 * Free Software Foundation; version 2.1 11 * 12 * RSTP library is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with RSTP library; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 **********************************************************************/ 22 23 /* Generic (abstract) state machine : 17.13, 17.14 */ 24 25 #include "base.h" 26 #include "statmch.h" 27 #include "stp_vectors.h" 28 29 #if STP_DBG 30 # include "stpm.h" 31 #endif 32 33 STATE_MACH_T * 34 STP_state_mach_create (void (*concreteEnterState) (STATE_MACH_T*), 35 Bool (*concreteCheckCondition) (STATE_MACH_T*), 36 char *(*concreteGetStatName) (int), 37 void *owner, char *name) 38 { 39 STATE_MACH_T *this; 40 41 STP_MALLOC(this, STATE_MACH_T, "state machine"); 42 43 this->State = BEGIN; 44 this->name = (char*) strdup (name); 45 this->changeState = False; 46 #if STP_DBG 47 this->debug = False; 48 this->ignoreHop2State = BEGIN; 49 #endif 50 this->concreteEnterState = concreteEnterState; 51 this->concreteCheckCondition = concreteCheckCondition; 52 this->concreteGetStatName = concreteGetStatName; 53 this->owner.owner = owner; 54 55 return this; 56 } 57 58 void 59 STP_state_mach_delete (STATE_MACH_T *this) 60 { 61 free (this->name); 62 STP_FREE(this, "state machine"); 63 } 64 65 Bool 66 STP_check_condition (STATE_MACH_T* this) 67 { 68 Bool bret; 69 70 bret = (*(this->concreteCheckCondition)) (this); 71 if (bret) { 72 this->changeState = True; 73 } 74 75 return bret; 76 } 77 78 Bool 79 STP_change_state (STATE_MACH_T* this) 80 { 81 register int number_of_loops; 82 83 for (number_of_loops = 0; ; number_of_loops++) { 84 if (! this->changeState) break; 85 (*(this->concreteEnterState)) (this); 86 this->changeState = False; 87 (void) STP_check_condition (this); 88 } 89 90 return number_of_loops; 91 } 92 93 Bool 94 STP_hop_2_state (STATE_MACH_T* this, unsigned int new_state) 95 { 96 #ifdef STP_DBG 97 switch (this->debug) { 98 case 0: break; 99 case 1: 100 if (new_state == this->State || new_state == this->ignoreHop2State) break; 101 stp_trace ("%-8s(%s-%s): %s=>%s", 102 this->name, 103 *this->owner.port->owner->name ? this->owner.port->owner->name : "Glbl", 104 this->owner.port->port_name, 105 (*(this->concreteGetStatName)) (this->State), 106 (*(this->concreteGetStatName)) (new_state)); 107 break; 108 case 2: 109 if (new_state == this->State) break; 110 stp_trace ("%s(%s): %s=>%s", 111 this->name, 112 *this->owner.stpm->name ? this->owner.stpm->name : "Glbl", 113 (*(this->concreteGetStatName)) (this->State), 114 (*(this->concreteGetStatName)) (new_state)); 115 break; 116 } 117 #endif 118 119 this->State = new_state; 120 this->changeState = True; 121 return True; 122 } 123 124