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
disableLearning(STATE_MACH_T * this)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
enableLearning(STATE_MACH_T * this)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
disableForwarding(STATE_MACH_T * this)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
enableForwarding(STATE_MACH_T * this)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
STP_sttrans_enter_state(STATE_MACH_T * this)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
STP_sttrans_check_conditions(STATE_MACH_T * this)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