stp_operation.c
Go to the documentation of this file.
1 /**
2  * @file stp_operation.c
3  * @brief Operation of the protocol
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSTP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL STP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stp/stp.h"
36 #include "stp/stp_operation.h"
37 #include "stp/stp_procedures.h"
38 #include "stp/stp_conditions.h"
39 #include "stp/stp_misc.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (STP_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Received Configuration BPDU (8.7.1)
48  * @param[in] port Pointer to the bridge port context
49  * @param[in] bpdu Pointer to the received Configuration BPDU
50  **/
51 
53 {
54  bool_t rootBridge;
55  StpBridgeContext *context;
56 
57  //Point to the STP bridge context
58  context = port->context;
59 
60  //Check port state
61  if(port->state != STP_PORT_STATE_DISABLED && port->macOperState)
62  {
63  //Check if the Configuration BPDU received conveys protocol information
64  //that supersedes that already held for the port
65  if(stpSupersedesPortInfo(port, bpdu))
66  {
67  //Test whether the bridge is currently the Root
68  rootBridge = stpRootBridge(context);
69 
70  //The Record Configuration Information procedure is used
72  //The Configuration Update procedure is used
73  stpConfigUpdate(context);
74  //The Port State Selection procedure is used
75  stpPortStateSelection(context);
76 
77  //Check if the Bridge was selected as the Root prior to Configuration
78  //Update, but is no longer
79  if(rootBridge && !stpRootBridge(context))
80  {
81  //The Hello Timer is stopped
82  stpStopTimer(&context->helloTimer);
83 
84  //Check if the Topology Change Detected flag parameter is set
85  if(context->topologyChangeDetected)
86  {
87  //The Topology Change Timer is stopped, the Transmit Topology
88  //Change Notification BPDU procedure is used, and the Topology
89  //Change Notification Timer is started
90  stpStopTimer(&context->topologyChangeTimer);
91  stpTransmitTcnBpdu(context);
92  stpStartTimer(&context->tcnTimer, 0);
93  }
94  }
95 
96  //Check if the Configuration BPDU was received on the Root port
97  if(stpRootPort(port))
98  {
99  //The Record Configuration Timeout Values and the Configuration
100  //BPDU Generation (8.6.4) procedures are used
101  stpRecordConfigTimeoutValues(context, bpdu);
102  stpConfigBpduGeneration(context);
103 
104  //Check if the Topology Change Acknowledgment flag parameter is set
105  if((bpdu->flags & STP_BPDU_FLAG_TC_ACK) != 0)
106  {
107  //The Topology Change Acknowledged procedure is used
108  stpTopologyChangeAcked(context);
109  }
110  }
111  }
112  else
113  {
114  //If the Configuration BPDU received does not convey information
115  //superseding that already held for the port and that port is the
116  //Designated port for the LAN to which it is attached, then the Reply
117  //to Configuration BPDU procedure is used
119  {
121  }
122  }
123  }
124 }
125 
126 
127 /**
128  * @brief Received Topology Change Notification BPDU (8.7.2)
129  * @param[in] port Pointer to the bridge port context
130  * @param[in] bpdu Pointer to the received TCN BPDU
131  **/
132 
134 {
135  //Check port state
136  if(port->state != STP_PORT_STATE_DISABLED && port->macOperState)
137  {
138  //Check whether the port on which the Topology Change Notification BPDU
139  //was received is the Designated Port for the LAN to which it is attached
141  {
142  //The Topology Change Detection procedure is used
144  //The Acknowledge Topology Change procedure is used
146  }
147  }
148 }
149 
150 
151 /**
152  * @brief Hello Timer expiry (8.7.3)
153  * @param[in] context Pointer to the STP bridge context
154  **/
155 
157 {
158  //The Configuration BPDU Generation procedure is used and the Hello Timer
159  //is started
160  stpConfigBpduGeneration(context);
161  stpStartTimer(&context->helloTimer, 0);
162 }
163 
164 
165 /**
166  * @brief Message Age Timer expiry (8.7.4)
167  * @param[in] port Pointer to the bridge port context
168  **/
169 
171 {
172  bool_t rootBridge;
173  StpBridgeContext *context;
174 
175  //Point to the STP bridge context
176  context = port->context;
177 
178  //Test whether the bridge is currently the Root
179  rootBridge = stpRootBridge(context);
180 
181  //The procedure to Become Designated Port is used for the port for which
182  //Message Age Timer has expired
184 
185  //The Configuration Update procedure is used
186  stpConfigUpdate(context);
187  //The Port State Selection procedure is used
188  stpPortStateSelection(context);
189 
190  //Check if the bridge is selected as the Root following Configuration Update
191  if(!rootBridge && stpRootBridge(context))
192  {
193  //The Max Age, Hello Time, and Forward Delay parameters held by the
194  //bridge are set to the values of the Bridge Max Age, Bridge Hello Time,
195  //and Bridge Forward Delay parameters
196  context->maxAge = context->bridgeMaxAge;
197  context->helloTime = context->bridgeHelloTime;
198  context->forwardDelay = context->bridgeForwardDelay;
199 
200  //The Topology Change Detection procedure is used
202  //The Topology Change Notification Timer is stopped
203  stpStopTimer(&context->tcnTimer);
204 
205  //The Configuration BPDU Generation procedure is used and the Hello
206  //Timer is started
207  stpConfigBpduGeneration(context);
208  stpStartTimer(&context->helloTimer, 0);
209  }
210 }
211 
212 
213 /**
214  * @brief Forward Delay Timer expiry (8.7.5)
215  * @param[in] port Pointer to the bridge port context
216  **/
217 
219 {
220  StpBridgeContext *context;
221 
222  //Point to the STP bridge context
223  context = port->context;
224 
225  //Check the state of the port
226  if(port->state == STP_PORT_STATE_LISTENING)
227  {
228  //If the state of the port for which the Forward Delay Timer has expired
229  //was Listening, then the Port State is set to Learning
231 
232  //The Forward Delay Timer is restarted
233  stpStartTimer(&port->forwardDelayTimer, 0);
234  }
235  else if(port->state == STP_PORT_STATE_LEARNING)
236  {
237  //If the state of the port for which the Forward Delay Timer has expired
238  //was Learning, then the Port State is set to Forwarding
240 
241  //Check if the bridge is the Designated Bridge for at least one of the
242  //LANs to which its ports are attached and the Change Detection Enabled
243  //parameter for the port is set
244  if(stpDesignatedBridge(context) && port->changeDetectionEnabled)
245  {
246  //The Topology Change Detection procedure is invoked
248  }
249  }
250  else
251  {
252  //Just for sanity
253  }
254 }
255 
256 
257 /**
258  * @brief Topology Change Notification Timer expiry (8.7.6)
259  * @param[in] context Pointer to the STP bridge context
260  **/
261 
263 {
264  //The Transmit Topology Change Notification BPDU procedure is used
265  stpTransmitTcnBpdu(context);
266  //The Topology Change Notification Timer is restarted
267  stpStartTimer(&context->tcnTimer, 0);
268 }
269 
270 
271 /**
272  * @brief Topology Change Timer expiry (8.7.7)
273  * @param[in] context Pointer to the STP bridge context
274  **/
275 
277 {
278  //The Topology Change Detected flag parameter held by the Bridge is reset
279  context->topologyChangeDetected = FALSE;
280  //The Topology Change flag parameter held by the Bridge is reset
281  stpUpdateTopologyChange(context, FALSE);
282 }
283 
284 
285 /**
286  * @brief Hold Timer expiry (8.7.8)
287  * @param[in] port Pointer to the bridge port context
288  **/
289 
291 {
292  //If the Configuration Pending flag parameter for the port for which the
293  //Hold Timer has expired is set, the Transmit Configuration BPDU procedure
294  //is invoked for that port
295  if(port->configPending)
296  {
298  }
299 }
300 
301 #endif
void stpReceivedConfigBpdu(StpBridgePort *port, const StpBpdu *bpdu)
Received Configuration BPDU (8.7.1)
Definition: stp_operation.c:52
int bool_t
Definition: compiler_port.h:53
void stpBecomeDesignatedPort(StpBridgePort *port)
Become Designated port (8.6.10)
void stpHelloTimerExpiry(StpBridgeContext *context)
Hello Timer expiry (8.7.3)
void stpReplyToConfigBpdu(StpBridgePort *port)
Reply to Configuration BPDU (8.6.5)
Operation of the protocol.
void stpUpdateTopologyChange(StpBridgeContext *context, bool_t value)
Set the Topology Change flag.
Definition: stp_misc.c:325
void stpReceivedTcnBpdu(StpBridgePort *port, const StpBpdu *bpdu)
Received Topology Change Notification BPDU (8.7.2)
@ STP_PORT_STATE_LEARNING
Definition: stp_common.h:113
void stpTransmitTcnBpdu(StpBridgeContext *context)
Transmit Topology Change Notification BPDU (8.6.6)
void stpUpdatePortState(StpBridgePort *port, StpPortState state)
Set port state.
Definition: stp_misc.c:358
StpBpdu
Definition: stp_bpdu.h:99
void stpForwardDelayTimerExpiry(StpBridgePort *port)
Forward Delay Timer expiry (8.7.5)
@ STP_PORT_STATE_DISABLED
Definition: stp_common.h:109
#define StpBridgePort
Definition: stp.h:40
@ STP_PORT_STATE_FORWARDING
Definition: stp_common.h:114
STP (Spanning Tree Protocol)
#define StpBridgeContext
Definition: stp.h:36
bool_t stpRootPort(StpBridgePort *port)
Test whether a given port is the Root port for the bridge.
void stpMessageAgeTimerExpiry(StpBridgePort *port)
Message Age Timer expiry (8.7.4)
#define FALSE
Definition: os_port.h:46
void stpTransmitConfigBpdu(StpBridgePort *port)
Transmit Configuration BPDU (8.6.1)
bool_t stpSupersedesPortInfo(StpBridgePort *port, const StpBpdu *bpdu)
Check whether the protocol information supersedes that already held for a port.
void stpTopologyChangeDetection(StpBridgeContext *context)
Topology change detection (8.6.14)
@ STP_PORT_STATE_LISTENING
Definition: stp_common.h:112
void stpAckTopologyChange(StpBridgePort *port)
Acknowledge topology change (8.6.16)
void stpRecordConfigInfo(StpBridgePort *port, const StpBpdu *bpdu)
Record configuration information (8.6.2)
bool_t stpRootBridge(StpBridgeContext *context)
Test whether the bridge is the Root bridge.
void stpTopologyChangeTimerExpiry(StpBridgeContext *context)
Topology Change Timer expiry (8.7.7)
void stpRecordConfigTimeoutValues(StpBridgeContext *context, const StpBpdu *bpdu)
Record configuration timeout values (8.6.3)
void stpTcnTimerExpiry(StpBridgeContext *context)
Topology Change Notification Timer expiry (8.7.6)
Elements of procedures.
@ STP_BPDU_FLAG_TC_ACK
Definition: stp_bpdu.h:69
void stpStartTimer(StpTimer *timer, uint_t value)
Start timer.
Definition: stp_misc.c:729
uint16_t port
Definition: dns_common.h:267
STP algorithm conditions.
void stpHoldTimerExpiry(StpBridgePort *port)
Hold Timer expiry (8.7.8)
STP helper functions.
void stpConfigUpdate(StpBridgeContext *context)
Configuration update (8.6.7)
void stpConfigBpduGeneration(StpBridgeContext *context)
Configuration BPDU generation (8.6.4)
bool_t stpDesignatedBridge(StpBridgeContext *context)
Test whether the bridge is the Designated bridge for at least one LAN.
bool_t stpDesignatedPort(StpBridgePort *port)
Test whether a given port is a Designated port.
void stpStopTimer(StpTimer *timer)
Stop timer.
Definition: stp_misc.c:743
Debugging facilities.
void stpTopologyChangeAcked(StpBridgeContext *context)
Topology change acknowledged (8.6.15)
void stpPortStateSelection(StpBridgeContext *context)
Port state selection (8.6.11)