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