rstp_pim.c
Go to the documentation of this file.
1 /**
2  * @file rstp_pim.c
3  * @brief Port Information state machine (PIM)
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 RSTP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "rstp/rstp.h"
36 #include "rstp/rstp_fsm.h"
37 #include "rstp/rstp_pim.h"
38 #include "rstp/rstp_procedures.h"
39 #include "rstp/rstp_misc.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (RSTP_SUPPORT == ENABLED)
44 
45 //PIM state machine's states
47 {
48  {RSTP_PIM_STATE_DISABLED, "DISABLED"},
49  {RSTP_PIM_STATE_AGED, "AGED"},
50  {RSTP_PIM_STATE_UPDATE, "UPDATE"},
51  {RSTP_PIM_STATE_SUPERIOR_DESIGNATED, "SUPERIOR_DESIGNATED"},
52  {RSTP_PIM_STATE_REPEATED_DESIGNATED, "REPEATED_DESIGNATED"},
53  {RSTP_PIM_STATE_INFERIOR_DESIGNATED, "INFERIOR_DESIGNATED"},
54  {RSTP_PIM_STATE_NOT_DESIGNATED, "NOT_DESIGNATED"},
55  {RSTP_PIM_STATE_OTHER, "OTHER"},
56  {RSTP_PIM_STATE_CURRENT, "CURRENT"},
57  {RSTP_PIM_STATE_RECEIVE, "RECEIVE"}
58 };
59 
60 
61 /**
62  * @brief PIM state machine initialization
63  * @param[in] port Pointer to the bridge port context
64  **/
65 
67 {
68  //Enter initial state
70 }
71 
72 
73 /**
74  * @brief PIM state machine implementation
75  * @param[in] port Pointer to the bridge port context
76  **/
77 
79 {
80  //A global transition can occur from any of the possible states
81  if(!port->portEnabled && port->infoIs != RSTP_INFO_IS_DISABLED)
82  {
83  //When the condition associated with a global transition is met, it
84  //supersedes all other exit conditions
86  }
87  else
88  {
89  //All conditions for the current state are evaluated continuously until one
90  //of the conditions is met (refer to IEEE Std 802.1D-2004, section 17.16)
91  switch(port->pimState)
92  {
93  //DISABLED state?
95  //Evaluate conditions for the current state
96  if(port->rcvdMsg)
97  {
98  //Switch to DISABLED state
100  }
101  else if(port->portEnabled)
102  {
103  //Switch to AGED state
105  }
106  else
107  {
108  //Just for sanity
109  }
110 
111  break;
112 
113  //AGED state?
114  case RSTP_PIM_STATE_AGED:
115  //Evaluate conditions for the current state
116  if(port->selected && port->updtInfo)
117  {
118  //Switch to UPDATE state
120  }
121 
122  break;
123 
124  //UPDATE, SUPERIOR_DESIGNATED, REPEATED_DESIGNATED, INFERIOR_DESIGNATED,
125  //NOT_DESIGNATED or OTHER state?
132  //Unconditional transition (UCT) to CURRENT state
134  break;
135 
136  //CURRENT state?
138  //Evaluate conditions for the current state
139  if(port->selected && port->updtInfo)
140  {
141  //Switch to UPDATE state
143  }
144  else if(port->infoIs == RSTP_INFO_IS_RECEIVED &&
145  port->rcvdInfoWhile == 0 && !port->updtInfo && !port->rcvdMsg)
146  {
147  //Switch to AGED state
149  }
150  else if(port->rcvdMsg && !port->updtInfo)
151  {
152  //Switch to RECEIVE state
154  }
155  else
156  {
157  //Just for sanity
158  }
159 
160  break;
161 
162  //RECEIVE state?
164  //Evaluate conditions for the current state
166  {
167  //Switch to SUPERIOR_DESIGNATED state
169  }
170  else if(port->rcvdInfo == RSTP_RCVD_INFO_REPEATED_DESIGNATED)
171  {
172  //Switch to REPEATED_DESIGNATED state
174  }
175  else if(port->rcvdInfo == RSTP_RCVD_INFO_INFERIOR_DESIGNATED)
176  {
177  //Switch to INFERIOR_DESIGNATED state
179  }
180  else if(port->rcvdInfo == RSTP_RCVD_INFO_INFERIOR_ROOT_ALTERNATE)
181  {
182  //Switch to NOT_DESIGNATED state
184  }
185  else if(port->rcvdInfo == RSTP_RCVD_INFO_OTHER)
186  {
187  //Switch to OTHER state
189  }
190  else
191  {
192  //Just for sanity
193  }
194 
195  break;
196 
197  //Invalid state?
198  default:
199  //Just for sanity
200  rstpFsmError(port->context);
201  break;
202  }
203  }
204 }
205 
206 
207 /**
208  * @brief Update PIM state machine state
209  * @param[in] port Pointer to the bridge port context
210  * @param[in] newState New state to switch to
211  **/
212 
214 {
215  //Dump the state transition
216  TRACE_VERBOSE("Port %" PRIu8 ": PIM state machine %s -> %s\r\n",
217  port->portIndex,
220 
221  //Switch to the new state
222  port->pimState = newState;
223 
224  //On entry to a state, the procedures defined for the state are executed
225  //exactly once (refer to IEEE Std 802.1D-2004, section 17.16)
226  switch(port->pimState)
227  {
228  //DISABLED state?
230  //Clear variables
231  port->rcvdMsg = FALSE;
232  port->proposing = FALSE;
233  port->proposed = FALSE;
234  port->agree = FALSE;
235  port->agreed = FALSE;
236  port->rcvdInfoWhile = 0;
237  port->infoIs = RSTP_INFO_IS_DISABLED;
238  port->reselect = TRUE;
239  port->selected = FALSE;
240  break;
241 
242  //AGED state?
243  case RSTP_PIM_STATE_AGED:
244  //The Spanning Tree information received by this port is aged out
245  port->infoIs = RSTP_INFO_IS_AGED;
246  port->reselect = TRUE;
247  port->selected = FALSE;
248  break;
249 
250  //UPDATE state?
252  port->proposing = FALSE;
253  port->proposed = FALSE;
254 
255  //Errata (refer to IEEE Std 802.1Q-2018, section 13.35)
256  port->agreed = port->agreed &&
258 
259 #if defined(RSTP_PIM_WORKAROUND_1)
260  //Errata
261  if(port->forward)
262  {
263  port->agreed = port->sendRstp;
264  }
265 #endif
266 
267  port->synced = port->synced && port->agreed;
268  port->portPriority = port->designatedPriority;
269  port->portTimes = port->designatedTimes;
270  port->updtInfo = FALSE;
271  port->infoIs = RSTP_INFO_IS_MINE;
272  port->newInfo = TRUE;
273  break;
274 
275  //SUPERIOR_DESIGNATED state?
277  port->agreed = FALSE;
278  port->proposing = FALSE;
281 
282  //Errata (refer to IEEE Std 802.1Q-2018, section 13.35)
283  port->agree = port->agree &&
285 
289  port->infoIs = RSTP_INFO_IS_RECEIVED;
290  port->reselect = TRUE;
291  port->selected = FALSE;
292  port->rcvdMsg = FALSE;
293  break;
294 
295  //REPEATED_DESIGNATED state?
300  port->rcvdMsg = FALSE;
301  break;
302 
303  //INFERIOR_DESIGNATED state?
306  port->rcvdMsg = FALSE;
307  break;
308 
309  //NOT_DESIGNATED state?
313  port->rcvdMsg = FALSE;
314  break;
315 
316  //OTHER state?
318  port->rcvdMsg = FALSE;
319  break;
320 
321  //CURRENT state?
323  //No procedure defined for this state
324  break;
325 
326  //RECEIVE state?
328  port->rcvdInfo = rstpRcvInfo(port);
329  break;
330 
331  //Invalid state?
332  default:
333  //Just for sanity
334  break;
335  }
336 
337  //The RSTP state machine is busy
338  port->context->busy = TRUE;
339 }
340 
341 #endif
@ RSTP_PIM_STATE_OTHER
Definition: rstp_pim.h:56
void rstpRecordTimes(RstpBridgePort *port)
Set portTimes variable (17.21.13)
@ RSTP_PIM_STATE_CURRENT
Definition: rstp_pim.h:57
RstpRcvdInfo rstpRcvInfo(RstpBridgePort *port)
Decode message priority and timer values from the received BPDU (17.21.8)
@ RSTP_INFO_IS_DISABLED
Definition: rstp.h:243
@ RSTP_PIM_STATE_DISABLED
Definition: rstp_pim.h:49
@ RSTP_PIM_STATE_UPDATE
Definition: rstp_pim.h:51
#define TRUE
Definition: os_port.h:50
@ RSTP_INFO_IS_RECEIVED
Definition: rstp.h:244
RSTP helper functions.
RstpPimState
Port Information machine states.
Definition: rstp_pim.h:48
@ RSTP_INFO_IS_AGED
Definition: rstp.h:246
@ RSTP_RCVD_INFO_INFERIOR_ROOT_ALTERNATE
Definition: rstp.h:232
void rstpRecordProposal(RstpBridgePort *port)
Record proposal (17.21.11)
@ RSTP_PIM_STATE_NOT_DESIGNATED
Definition: rstp_pim.h:55
void rstpRecordPriority(RstpBridgePort *port)
Record priority (17.21.12)
bool_t rstpBetterOrSameInfo(RstpBridgePort *port, RstpInfoIs newInfoIs)
Compare Spanning Tree information (17.21.1)
@ RSTP_PIM_STATE_REPEATED_DESIGNATED
Definition: rstp_pim.h:53
#define FALSE
Definition: os_port.h:46
void rstpPimFsm(RstpBridgePort *port)
PIM state machine implementation.
Definition: rstp_pim.c:78
void rstpPimInit(RstpBridgePort *port)
PIM state machine initialization.
Definition: rstp_pim.c:66
RSTP (Rapid Spanning Tree Protocol)
@ RSTP_RCVD_INFO_SUPERIOR_DESIGNATED
Definition: rstp.h:229
Port Information state machine (PIM)
void rstpRecordDispute(RstpBridgePort *port)
Record dispute (17.21.10)
@ RSTP_PIM_STATE_AGED
Definition: rstp_pim.h:50
@ RSTP_INFO_IS_MINE
Definition: rstp.h:245
@ RSTP_RCVD_INFO_REPEATED_DESIGNATED
Definition: rstp.h:230
const RstpParamName rstpPimStates[]
Definition: rstp_pim.c:46
uint16_t port
Definition: dns_common.h:267
@ RSTP_RCVD_INFO_INFERIOR_DESIGNATED
Definition: rstp.h:231
RSTP state machine procedures.
void rstpFsmError(RstpBridgeContext *context)
RSTP state machine error handler.
Definition: rstp_fsm.c:226
void rstpRecordAgreement(RstpBridgePort *port)
Record agreement (17.21.9)
@ RSTP_PIM_STATE_SUPERIOR_DESIGNATED
Definition: rstp_pim.h:52
void rstpSetTcFlags(RstpBridgePort *port)
Update rcvdTc, rcvdTcAck and rcvdTcn flags (17.21.17)
@ RSTP_PIM_STATE_RECEIVE
Definition: rstp_pim.h:58
Parameter value/name binding.
Definition: rstp_misc.h:48
void rstpPimChangeState(RstpBridgePort *port, RstpPimState newState)
Update PIM state machine state.
Definition: rstp_pim.c:213
@ RSTP_RCVD_INFO_OTHER
Definition: rstp.h:233
@ RSTP_PIM_STATE_INFERIOR_DESIGNATED
Definition: rstp_pim.h:54
void rstpUpdtRcvdInfoWhile(RstpBridgePort *port)
Update the Received Info timer (17.21.23)
const char_t * rstpGetParamName(uint_t value, const RstpParamName *paramList, size_t paramListLen)
Convert a parameter to string representation.
Definition: rstp_misc.c:883
Debugging facilities.
#define TRACE_VERBOSE(...)
Definition: debug.h:124
#define RstpBridgePort
Definition: rstp.h:40
#define arraysize(a)
Definition: os_port.h:71
Rapid Spanning Tree state machines.