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 State Transition state machine : 17.24 */ 24 25 #include "base.h" 26 #include "stpm.h" 27 #include "stp_to.h" 28 29 #define STATES { \ 30 CHOOSE(DISCARDING), \ 31 CHOOSE(LEARNING), \ 32 CHOOSE(FORWARDING) \ 33 } 34 35 #define GET_STATE_NAME STP_sttrans_get_state_name 36 #include "choose.h" 37 38 39 #ifdef STRONGLY_SPEC_802_1W 40 static Bool 41 disableLearning (STATE_MACH_T *this) 42 { 43 register PORT_T *port = this->owner.port; 44 45 return STP_OUT_set_learning (port->port_index, port->owner->vlan_id, False); 46 } 47 48 static Bool 49 enableLearning (STATE_MACH_T *this) 50 { 51 register PORT_T *port = this->owner.port; 52 53 return STP_OUT_set_learning (port->port_index, port->owner->vlan_id, True); 54 } 55 56 static Bool 57 disableForwarding (STATE_MACH_T *this) 58 { 59 register PORT_T *port = this->owner.port; 60 61 return STP_OUT_set_forwarding (port->port_index, port->owner->vlan_id, False); 62 } 63 64 static Bool 65 enableForwarding (STATE_MACH_T *this) 66 { 67 register PORT_T *port = this->owner.port; 68 69 return STP_OUT_set_forwarding (port->port_index, port->owner->vlan_id, True); 70 } 71 #endif 72 73 void 74 STP_sttrans_enter_state (STATE_MACH_T *this) 75 { 76 register PORT_T *port = this->owner.port; 77 78 switch (this->State) { 79 case BEGIN: 80 case DISCARDING: 81 port->learning = False; 82 port->forwarding = False; 83 #ifdef STRONGLY_SPEC_802_1W 84 disableLearning (this); 85 disableForwarding (this); 86 #else 87 STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_DISCARDING); 88 #endif 89 break; 90 case LEARNING: 91 port->learning = True; 92 #ifdef STRONGLY_SPEC_802_1W 93 enableLearning (this); 94 #else 95 STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_LEARNING); 96 #endif 97 break; 98 case FORWARDING: 99 port->tc = !port->operEdge; 100 port->forwarding = True; 101 #ifdef STRONGLY_SPEC_802_1W 102 enableForwarding (this); 103 #else 104 STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_FORWARDING); 105 #endif 106 break; 107 } 108 109 } 110 111 Bool 112 STP_sttrans_check_conditions (STATE_MACH_T *this) 113 { 114 register PORT_T *port = this->owner.port; 115 116 switch (this->State) { 117 case BEGIN: 118 return STP_hop_2_state (this, DISCARDING); 119 case DISCARDING: 120 if (port->learn) { 121 return STP_hop_2_state (this, LEARNING); 122 } 123 break; 124 case LEARNING: 125 if (port->forward) { 126 return STP_hop_2_state (this, FORWARDING); 127 } 128 if (!port->learn) { 129 return STP_hop_2_state (this, DISCARDING); 130 } 131 break; 132 case FORWARDING: 133 if (!port->forward) { 134 return STP_hop_2_state (this, DISCARDING); 135 } 136 break; 137 } 138 139 return False; 140 } 141