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 /* Port Protocol Migration state machine : 17.26 */ 24 25 #include "base.h" 26 #include "stpm.h" 27 28 #define STATES { \ 29 CHOOSE(INIT), \ 30 CHOOSE(SEND_RSTP), \ 31 CHOOSE(SENDING_RSTP), \ 32 CHOOSE(SEND_STP), \ 33 CHOOSE(SENDING_STP) \ 34 } 35 36 #define GET_STATE_NAME STP_migrate_get_state_name 37 #include "choose.h" 38 39 #define MigrateTime 3 /* 17,16.4 */ 40 41 void 42 STP_migrate_enter_state (STATE_MACH_T* this) 43 { 44 register PORT_T* port = this->owner.port; 45 46 switch (this->State) { 47 case BEGIN: 48 case INIT: 49 port->initPm = True; 50 port->mcheck = False; 51 break; 52 case SEND_RSTP: 53 port->mdelayWhile = MigrateTime; 54 port->mcheck = port->initPm = False; 55 port->sendRSTP = True; 56 break; 57 case SENDING_RSTP: 58 port->rcvdRSTP = port->rcvdSTP = False; 59 break; 60 case SEND_STP: 61 port->mdelayWhile = MigrateTime; 62 port->sendRSTP = False; 63 port->initPm = False; 64 break; 65 case SENDING_STP: 66 port->rcvdRSTP = port->rcvdSTP = False; 67 break; 68 } 69 } 70 71 Bool 72 STP_migrate_check_conditions (STATE_MACH_T* this) 73 { 74 register PORT_T* port = this->owner.port; 75 76 if ((!port->portEnabled && !port->initPm) || BEGIN == this->State) 77 return STP_hop_2_state (this, INIT); 78 79 switch (this->State) { 80 case INIT: 81 if (port->portEnabled) { 82 return STP_hop_2_state (this, (port->owner->ForceVersion >= 2) ? 83 SEND_RSTP : SEND_STP); 84 } 85 break; 86 case SEND_RSTP: 87 return STP_hop_2_state (this, SENDING_RSTP); 88 case SENDING_RSTP: 89 if (port->mcheck) 90 return STP_hop_2_state (this, SEND_RSTP); 91 if (port->mdelayWhile && 92 (port->rcvdSTP || port->rcvdRSTP)) { 93 return STP_hop_2_state (this, SENDING_RSTP); 94 } 95 96 if (!port->mdelayWhile && port->rcvdSTP) { 97 return STP_hop_2_state (this, SEND_STP); 98 } 99 100 if (port->owner->ForceVersion < 2) { 101 return STP_hop_2_state (this, SEND_STP); 102 } 103 104 break; 105 case SEND_STP: 106 return STP_hop_2_state (this, SENDING_STP); 107 case SENDING_STP: 108 if (port->mcheck) 109 return STP_hop_2_state (this, SEND_RSTP); 110 if (port->mdelayWhile && 111 (port->rcvdSTP || port->rcvdRSTP)) 112 return STP_hop_2_state (this, SENDING_STP); 113 if (!port->mdelayWhile && port->rcvdRSTP) 114 return STP_hop_2_state (this, SEND_RSTP); 115 break; 116 } 117 return False; 118 } 119 120