rstp_mgmt.c
Go to the documentation of this file.
1 /**
2  * @file rstp_mgmt.c
3  * @brief Management of the RSTP bridge
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.0
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_conditions.h"
38 #include "rstp/rstp_misc.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (RSTP_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Set protocol version
47  * @param[in] context Pointer to the RSTP bridge context
48  * @param[in] value Protocol version
49  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
50  * value and commits the change if the value is valid. If FALSE, the bridge
51  * only performs the verification and does not take any further action
52  * @return Error code
53  **/
54 
56  bool_t commit)
57 {
58  //Make sure the RSTP bridge context is valid
59  if(context == NULL)
60  return ERROR_WRITE_FAILED;
61 
62  //Check parameter
64  return ERROR_WRONG_VALUE;
65 
66  //Commit phase?
67  if(commit)
68  {
69  //Any parameter change?
70  if(value != context->params.forceProtocolVersion)
71  {
72  //Set the Force Protocol Version variable
73  context->params.forceProtocolVersion = value;
74 
75  //The Spanning Tree Protocol entity shall be reinitialized if the Force
76  //Protocol Version is modified
77  rstpFsmInit(context);
78  }
79  }
80 
81  //Successful processing
82  return NO_ERROR;
83 }
84 
85 
86 /**
87  * @brief Set bridge priority
88  * @param[in] context Pointer to the RSTP bridge context
89  * @param[in] value Bridge priority
90  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
91  * value and commits the change if the value is valid. If FALSE, the bridge
92  * only performs the verification and does not take any further action
93  * @return Error code
94  **/
95 
97  bool_t commit)
98 {
99  uint_t i;
100 
101  //Make sure the RSTP bridge context is valid
102  if(context == NULL)
103  return ERROR_WRITE_FAILED;
104 
105  //Permissible values are 0-61440, in steps of 4096
106  if(value > 61440 || (value % 4096) != 0)
107  return ERROR_WRONG_VALUE;
108 
109  //Commit phase?
110  if(commit)
111  {
112  //Any parameter change?
113  if(value != context->bridgeId.priority)
114  {
115  //The Bridge Priority parameter is updated using the supplied value
116  context->bridgeId.priority = value;
117 
118  //The first (RootBridgeID) and third (DesignatedBridgeID) components
119  //of the bridge priority vector are both equal to the value of the
120  //Bridge Identifier. The other components are zero
121  context->bridgePriority.rootBridgeId = context->bridgeId;
122  context->bridgePriority.rootPathCost = 0;
123  context->bridgePriority.designatedBridgeId = context->bridgeId;
124  context->bridgePriority.designatedPortId = 0;
125  context->bridgePriority.bridgePortId = 0;
126 
127  //The spanning tree priority vectors and port role assignments for a
128  //bridge shall be recomputed by clearing selected and setting reselect
129  //(refer to IEEE Std 802.1D-2004, section 17.13)
130  for(i = 0; i < context->numPorts; i++)
131  {
132  context->ports[i].selected = FALSE;
133  context->ports[i].reselect = TRUE;
134  }
135 
136  //Update RSTP state machine
137  rstpFsm(context);
138  }
139  }
140 
141  //Successful processing
142  return NO_ERROR;
143 }
144 
145 
146 /**
147  * @brief Set Bridge Max Age parameter
148  * @param[in] context Pointer to the RSTP bridge context
149  * @param[in] value Value of the Bridge Max Age parameter, in seconds
150  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
151  * value and commits the change if the value is valid. If FALSE, the bridge
152  * only performs the verification and does not take any further action
153  * @return Error code
154  **/
155 
157  bool_t commit)
158 {
159  uint_t i;
160 
161  //Make sure the RSTP bridge context is valid
162  if(context == NULL)
163  return ERROR_WRITE_FAILED;
164 
165  //If the value of the Bridge Max Age is outside the specified range, then
166  //no action shall be taken
167  if(value < RSTP_MIN_BRIDGE_MAX_AGE || value > RSTP_MAX_BRIDGE_MAX_AGE)
168  return ERROR_WRONG_VALUE;
169 
170  //To support interoperability with legacy bridges, a bridge shall enforce
171  //the following relationships (refer to IEEE Std 802.1D-2004, section 17.14)
172  if(!rstpCheckBridgeParams(value, context->params.bridgeHelloTime,
173  context->params.bridgeForwardDelay))
174  {
176  }
177 
178  //Commit phase?
179  if(commit)
180  {
181  //Any parameter change?
182  if(value != context->params.bridgeMaxAge)
183  {
184  //The Bridge Max Age parameter specifies the value that all bridges use
185  //for MaxAge when this bridge is acting as the root
186  context->params.bridgeMaxAge = value;
187  context->bridgeTimes.maxAge = value;
188 
189  //Recompute the designatedTimes for each port
190  for(i = 0; i < context->numPorts; i++)
191  {
192  context->ports[i].selected = FALSE;
193  context->ports[i].reselect = TRUE;
194  }
195 
196  //Update RSTP state machine
197  rstpFsm(context);
198  }
199  }
200 
201  //Successful processing
202  return NO_ERROR;
203 }
204 
205 
206 /**
207  * @brief Set Bridge Hello Time parameter
208  * @param[in] context Pointer to the RSTP bridge context
209  * @param[in] value Value of the Bridge Hello Time parameter, in seconds
210  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
211  * value and commits the change if the value is valid. If FALSE, the bridge
212  * only performs the verification and does not take any further action
213  * @return Error code
214  **/
215 
217  bool_t commit)
218 {
219  uint_t i;
220 
221  //Make sure the RSTP bridge context is valid
222  if(context == NULL)
223  return ERROR_WRITE_FAILED;
224 
225  //If the value of the Bridge Hello Time is outside the specified range, then
226  //no action shall be taken
227  if(value < RSTP_MIN_BRIDGE_HELLO_TIME || value > RSTP_MAX_BRIDGE_HELLO_TIME)
228  return ERROR_WRONG_VALUE;
229 
230  //To support interoperability with legacy bridges, a bridge shall enforce
231  //the following relationship (refer to IEEE Std 802.1D-2004, section 17.14)
232  if(!rstpCheckBridgeParams(context->params.bridgeMaxAge, value,
233  context->params.bridgeForwardDelay))
234  {
236  }
237 
238  //Commit phase?
239  if(commit)
240  {
241  //Any parameter change?
242  if(value != context->params.bridgeHelloTime)
243  {
244  //The Bridge Hello Time parameter specifies the value that all bridges
245  //use for HelloTime when this bridge is acting as the root
246  context->params.bridgeHelloTime = value;
247  context->bridgeTimes.helloTime = value;
248 
249  //Recompute the designatedTimes for each port
250  for(i = 0; i < context->numPorts; i++)
251  {
252  context->ports[i].selected = FALSE;
253  context->ports[i].reselect = TRUE;
254  }
255 
256  //Update RSTP state machine
257  rstpFsm(context);
258  }
259  }
260 
261  //Successful processing
262  return NO_ERROR;
263 }
264 
265 
266 /**
267  * @brief Set Bridge Forward Delay parameter
268  * @param[in] context Pointer to the RSTP bridge context
269  * @param[in] value Value of the Bridge Forward Delay parameter, in seconds
270  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
271  * value and commits the change if the value is valid. If FALSE, the bridge
272  * only performs the verification and does not take any further action
273  * @return Error code
274  **/
275 
277  bool_t commit)
278 {
279  uint_t i;
280 
281  //Make sure the RSTP bridge context is valid
282  if(context == NULL)
283  return ERROR_WRITE_FAILED;
284 
285  //If the value of the Bridge Forward Delay is outside the specified range,
286  //then no action shall be taken
289  {
290  return ERROR_WRONG_VALUE;
291  }
292 
293  //To support interoperability with legacy bridges, a bridge shall enforce
294  //the following relationship (refer to IEEE Std 802.1D-2004, section 17.14)
295  if(!rstpCheckBridgeParams(context->params.bridgeMaxAge,
296  context->params.bridgeHelloTime, value))
297  {
299  }
300 
301  //Commit phase?
302  if(commit)
303  {
304  //Any parameter change?
305  if(value != context->params.bridgeForwardDelay)
306  {
307  //The Bridge Forward Delay parameter specifies the value that all
308  //bridges use for ForwardDelay when this bridge is acting as the root
309  context->params.bridgeForwardDelay = value;
310  context->bridgeTimes.forwardDelay = value;
311 
312  //Recompute the designatedTimes for each port
313  for(i = 0; i < context->numPorts; i++)
314  {
315  context->ports[i].selected = FALSE;
316  context->ports[i].reselect = TRUE;
317  }
318 
319  //Update RSTP state machine
320  rstpFsm(context);
321  }
322  }
323 
324  //Successful processing
325  return NO_ERROR;
326 }
327 
328 
329 /**
330  * @brief Set Transmit Hold Count parameter
331  * @param[in] context Pointer to the RSTP bridge context
332  * @param[in] value Value of the Transmit Hold Count parameter
333  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
334  * value and commits the change if the value is valid. If FALSE, the bridge
335  * only performs the verification and does not take any further action
336  * @return Error code
337  **/
338 
340  bool_t commit)
341 {
342  uint_t i;
343 
344  //Make sure the RSTP bridge context is valid
345  if(context == NULL)
346  return ERROR_WRITE_FAILED;
347 
348  //If the value of the Transmit Hold Count is outside the specified range,
349  //then no action shall be taken
352  {
353  return ERROR_WRONG_VALUE;
354  }
355 
356  //Commit phase?
357  if(commit)
358  {
359  //Any parameter change?
360  if(value != context->params.transmitHoldCount)
361  {
362  //The Transmit Hold Count parameter specifies the value used by the
363  //Port Transmit state machine to limit the maximum transmission rate
364  context->params.transmitHoldCount = value;
365 
366  //If the Transmit Hold Count is modified the value of txCount for all
367  //ports shall be set to zero (refer to IEEE Std 802.1D-2004, section
368  //17.13)
369  for(i = 0; i < context->numPorts; i++)
370  {
371  context->ports[i].txCount = 0;
372  }
373  }
374  }
375 
376  //Successful processing
377  return NO_ERROR;
378 }
379 
380 
381 /**
382  * @brief Set Ageing Time parameter
383  * @param[in] context Pointer to the RSTP bridge context
384  * @param[in] value Value of the Ageing Time parameter
385  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
386  * value and commits the change if the value is valid. If FALSE, the bridge
387  * only performs the verification and does not take any further action
388  * @return Error code
389  **/
390 
392  bool_t commit)
393 {
394  //Make sure the RSTP bridge context is valid
395  if(context == NULL)
396  return ERROR_WRITE_FAILED;
397 
398  //If the value of the Ageing Time is outside the specified range, then no
399  //action shall be taken
400  if(value < RSTP_MIN_AGEING_TIME || value > RSTP_MAX_AGEING_TIME)
401  return ERROR_WRONG_VALUE;
402 
403  //Commit phase?
404  if(commit)
405  {
406  //Any parameter change?
407  if(value != context->params.ageingTime)
408  {
409  //The Ageing Time parameter is updated using the supplied value
410  context->params.ageingTime = value;
411 
412  //Check whether the rapid ageing timer is stopped
413  if(context->rapidAgeingWhile == 0)
414  {
415  //The value of the ageingTime parameter is normally Ageing Time
416  context->ageingTime = context->params.ageingTime;
417  //Set ageing time for dynamic filtering entries
418  rstpUpdateAgeingTime(context, context->ageingTime);
419  }
420  }
421  }
422 
423  //Successful processing
424  return NO_ERROR;
425 }
426 
427 
428 /**
429  * @brief Get the number of ports
430  * @param[in] context Pointer to the RSTP bridge context
431  * @param[out] value Number of ports
432  * @return Error code
433  **/
434 
436 {
437  //Check parameters
438  if(context == NULL || value == NULL)
439  return ERROR_READ_FAILED;
440 
441  //Retrieve the number of ports
442  *value = context->numPorts;
443 
444  //Successful processing
445  return NO_ERROR;
446 }
447 
448 
449 /**
450  * @brief Get assigned protocol version
451  * @param[in] context Pointer to the RSTP bridge context
452  * @param[out] value Protocol version
453  * @return Error code
454  **/
455 
457 {
458  //Check parameters
459  if(context == NULL || value == NULL)
460  return ERROR_READ_FAILED;
461 
462  //Retrieve the version of Spanning Tree Protocol the bridge is currently
463  //running
464  *value = context->params.forceProtocolVersion;
465 
466  //Successful processing
467  return NO_ERROR;
468 }
469 
470 
471 /**
472  * @brief Get the MAC address assigned to the bridge
473  * @param[in] context Pointer to the RSTP bridge context
474  * @param[out] value MAC address of the bridge
475  * @return Error code
476  **/
477 
479 {
480  //Check parameters
481  if(context == NULL || value == NULL)
482  return ERROR_READ_FAILED;
483 
484  //Retrieve the bridge identifier
485  *value = context->bridgeId.addr;
486 
487  //Successful processing
488  return NO_ERROR;
489 }
490 
491 
492 /**
493  * @brief Get the assigned bridge priority
494  * @param[in] context Pointer to the RSTP bridge context
495  * @param[out] value Bridge priority
496  * @return Error code
497  **/
498 
500 {
501  //Check parameters
502  if(context == NULL || value == NULL)
503  return ERROR_READ_FAILED;
504 
505  //Retrieve the bridge priority
506  *value = context->bridgeId.priority;
507 
508  //Successful processing
509  return NO_ERROR;
510 }
511 
512 
513 /**
514  * @brief Get the assigned value of the Bridge Max Age parameter
515  * @param[in] context Pointer to the RSTP bridge context
516  * @param[out] value Value of the Bridge Max Age parameter, in seconds
517  * @return Error code
518  **/
519 
521 {
522  //Check parameters
523  if(context == NULL || value == NULL)
524  return ERROR_READ_FAILED;
525 
526  //Retrieve the value of the Bridge Max Age parameter
527  *value = context->params.bridgeMaxAge;
528 
529  //Successful processing
530  return NO_ERROR;
531 }
532 
533 
534 /**
535  * @brief Get the assigned value of the Bridge Hello Time parameter
536  * @param[in] context Pointer to the RSTP bridge context
537  * @param[out] value Value of the Bridge Hello Time parameter, in seconds
538  * @return Error code
539  **/
540 
542 {
543  //Check parameters
544  if(context == NULL || value == NULL)
545  return ERROR_READ_FAILED;
546 
547  //Retrieve the value of the Bridge Hello Time parameter
548  *value = context->params.bridgeHelloTime;
549 
550  //Successful processing
551  return NO_ERROR;
552 }
553 
554 
555 /**
556  * @brief Get the assigned value of the Bridge Forward Delay parameter
557  * @param[in] context Pointer to the RSTP bridge context
558  * @param[out] value Value of the Bridge Forward Delay parameter, in seconds
559  * @return Error code
560  **/
561 
563 {
564  //Check parameters
565  if(context == NULL || value == NULL)
566  return ERROR_READ_FAILED;
567 
568  //Retrieve the value of the Bridge Forward Delay parameter
569  *value = context->params.bridgeForwardDelay;
570 
571  //Successful processing
572  return NO_ERROR;
573 }
574 
575 
576 /**
577  * @brief Get the assigned value of the Transmit Hold Count parameter
578  * @param[in] context Pointer to the RSTP bridge context
579  * @param[out] value Value of the Transmit Hold Count parameter
580  * @return Error code
581  **/
582 
584 {
585  //Check parameters
586  if(context == NULL || value == NULL)
587  return ERROR_READ_FAILED;
588 
589  //Retrieve the value of the Transmit Hold Count parameter
590  *value = context->params.transmitHoldCount;
591 
592  //Successful processing
593  return NO_ERROR;
594 }
595 
596 
597 /**
598  * @brief Get the assigned value of the Ageing Time parameter
599  * @param[in] context Pointer to the RSTP bridge context
600  * @param[out] value Value of the Ageing Time parameter
601  * @return Error code
602  **/
603 
605 {
606  //Check parameters
607  if(context == NULL || value == NULL)
608  return ERROR_READ_FAILED;
609 
610  //Retrieve the value of the Ageing Time parameter
611  *value = context->params.ageingTime;
612 
613  //Successful processing
614  return NO_ERROR;
615 }
616 
617 
618 /**
619  * @brief Get the bridge identifier of the root of the spanning tree
620  * @param[in] context Pointer to the RSTP bridge context
621  * @param[out] value Bridge identifier
622  * @return Error code
623  **/
624 
626 {
627  //Check parameters
628  if(context == NULL || value == NULL)
629  return ERROR_READ_FAILED;
630 
631  //Retrieve the bridge identifier of the root of the spanning tree, as
632  //determined by the Spanning Tree Protocol
633  *value = context->rootPriority.rootBridgeId;
634 
635  //Successful processing
636  return NO_ERROR;
637 }
638 
639 
640 /**
641  * @brief Get the current cost of the path to the root
642  * @param[in] context Pointer to the RSTP bridge context
643  * @param[out] value Root path cost
644  * @return Error code
645  **/
646 
648 {
649  //Check parameters
650  if(context == NULL || value == NULL)
651  return ERROR_READ_FAILED;
652 
653  //Retrieve the cost of the path to the root as seen from this bridge
654  *value = context->rootPriority.rootPathCost;
655 
656  //Successful processing
657  return NO_ERROR;
658 }
659 
660 
661 /**
662  * @brief Get the current root port
663  * @param[in] context Pointer to the RSTP bridge context
664  * @param[out] value Port number
665  * @return Error code
666  **/
667 
669 {
670  //Check parameters
671  if(context == NULL || value == NULL)
672  return ERROR_READ_FAILED;
673 
674  //Retrieve the port through which the path to the Root is established. This
675  //value not significant when the bridge is the Root, and is set to zero
676  *value = context->rootPortId & RSTP_PORT_NUM_MASK;
677 
678  //Successful processing
679  return NO_ERROR;
680 }
681 
682 
683 /**
684  * @brief Get the current Max Age value
685  * @param[in] context Pointer to the RSTP bridge context
686  * @param[out] value Max Age value, in seconds
687  * @return Error code
688  **/
689 
691 {
692  //Check parameters
693  if(context == NULL || value == NULL)
694  return ERROR_READ_FAILED;
695 
696  //Retrieve the maximum age of Spanning Tree Protocol information learned
697  //from the network on any port before it is discarded
698  *value = context->rootTimes.maxAge;
699 
700  //Successful processing
701  return NO_ERROR;
702 }
703 
704 
705 /**
706  * @brief Get the current Hello Time value
707  * @param[in] context Pointer to the RSTP bridge context
708  * @param[out] value Hello Time value, in seconds
709  * @return Error code
710  **/
711 
713 {
714  //Check parameters
715  if(context == NULL || value == NULL)
716  return ERROR_READ_FAILED;
717 
718  //Retrieve the amount of time between the transmission of Configuration
719  //bridge PDUs by this node on any port when it is the root of the spanning
720  //tree, or trying to become so
721  *value = context->rootTimes.helloTime;
722 
723  //Successful processing
724  return NO_ERROR;
725 }
726 
727 
728 /**
729  * @brief Get the current Forward Delay value
730  * @param[in] context Pointer to the RSTP bridge context
731  * @param[out] value Forward Delay value, in seconds
732  * @return Error code
733  **/
734 
736 {
737  //Check parameters
738  if(context == NULL || value == NULL)
739  return ERROR_READ_FAILED;
740 
741  //The Forward Delay value determines how long the port stays in each of the
742  //Listening and Learning states, which precede the Forwarding state
743  *value = context->rootTimes.forwardDelay;
744 
745  //Successful processing
746  return NO_ERROR;
747 }
748 
749 
750 /**
751  * @brief Get the number of topology changes
752  * @param[in] context Pointer to the RSTP bridge context
753  * @param[out] value Number of topology changes
754  * @return Error code
755  **/
756 
758 {
759  //Check parameters
760  if(context == NULL || value == NULL)
761  return ERROR_READ_FAILED;
762 
763  //Retrieve the number of topology changes
764  *value = context->topologyChangeCount;
765 
766  //Successful processing
767  return NO_ERROR;
768 }
769 
770 
771 /**
772  * @brief Get the time since a topology change was last detected
773  * @param[in] context Pointer to the RSTP bridge context
774  * @param[out] value Time since a topology change was last detected
775  * @return Error code
776  **/
777 
779  uint_t *value)
780 {
781  //Check parameters
782  if(context == NULL || value == NULL)
783  return ERROR_READ_FAILED;
784 
785  //Retrieve the time since a topology change was last detected by the bridge
786  *value = context->timeSinceTopologyChange;
787 
788  //Successful processing
789  return NO_ERROR;
790 }
791 
792 
793 /**
794  * @brief Set port priority
795  * @param[in] context Pointer to the RSTP bridge context
796  * @param[in] portIndex Port index
797  * @param[in] value Port priority
798  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
799  * value and commits the change if the value is valid. If FALSE, the bridge
800  * only performs the verification and does not take any further action
801  * @return Error code
802  **/
803 
805  uint8_t value, bool_t commit)
806 {
808 
809  //Make sure the RSTP bridge context is valid
810  if(context == NULL)
811  return ERROR_WRITE_FAILED;
812 
813  //Invalid port index?
814  if(portIndex < 1 || portIndex > context->numPorts)
815  return ERROR_INVALID_PORT;
816 
817  //Valid port priorities are in the range 0 through 240, in steps of 16
818  if(value > 240 || (value % 16) != 0)
819  return ERROR_WRONG_VALUE;
820 
821  //Point to the port that matches the specified port index
822  port = &context->ports[portIndex - 1];
823 
824  //Commit phase?
825  if(commit)
826  {
827  //Any parameter change?
828  if(value != ((port->portId & RSTP_PORT_PRIORITY_MASK) >> 8))
829  {
830  //The port identifier is updated using the supplied value
831  port->portId = (port->portId & RSTP_PORT_NUM_MASK) | (value << 8);
832 
833  //The spanning tree priority vectors and port role assignments for
834  //a bridge shall be recomputed by clearing selected and setting
835  //reselect (refer to IEEE Std 802.1D-2004, section 17.13)
836  port->selected = FALSE;
837  port->reselect = TRUE;
838 
839  //Update RSTP state machine
840  rstpFsm(context);
841  }
842  }
843 
844  //Successful processing
845  return NO_ERROR;
846 }
847 
848 
849 /**
850  * @brief Set administrative bridge port state
851  * @param[in] context Pointer to the RSTP bridge context
852  * @param[in] portIndex Port index
853  * @param[in] value Administrative bridge port state
854  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
855  * value and commits the change if the value is valid. If FALSE, the bridge
856  * only performs the verification and does not take any further action
857  * @return Error code
858  **/
859 
861  bool_t value, bool_t commit)
862 {
864 
865  //Make sure the RSTP bridge context is valid
866  if(context == NULL)
867  return ERROR_WRITE_FAILED;
868 
869  //Invalid port index?
870  if(portIndex < 1 || portIndex > context->numPorts)
871  return ERROR_INVALID_PORT;
872 
873  //Point to the port that matches the specified port index
874  port = &context->ports[portIndex - 1];
875 
876  //Commit phase?
877  if(commit)
878  {
879  //Any parameter change?
880  if(value != port->params.adminPortState)
881  {
882  //Update the administrative bridge port state
883  port->params.adminPortState = value;
884 
885  //The portEnabled variable is set if the MAC entity can transmit and
886  //receive frames to and from the attached LAN
887  port->portEnabled = port->macOperState && port->params.adminPortState;
888 
889  //Update RSTP state machine
890  rstpFsm(context);
891  }
892  }
893 
894  //Successful processing
895  return NO_ERROR;
896 }
897 
898 
899 /**
900  * @brief Set administrative port path cost
901  * @param[in] context Pointer to the RSTP bridge context
902  * @param[in] portIndex Port index
903  * @param[in] value Administrative port path cost
904  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
905  * value and commits the change if the value is valid. If FALSE, the bridge
906  * only performs the verification and does not take any further action
907  * @return Error code
908  **/
909 
911  uint32_t value, bool_t commit)
912 {
914 
915  //Make sure the RSTP bridge context is valid
916  if(context == NULL)
917  return ERROR_WRITE_FAILED;
918 
919  //Invalid port index?
920  if(portIndex < 1 || portIndex > context->numPorts)
921  return ERROR_INVALID_PORT;
922 
923  //Check the value of the parameter
925  return ERROR_WRONG_VALUE;
926 
927  //Point to the port that matches the specified port index
928  port = &context->ports[portIndex - 1];
929 
930  //Commit phase?
931  if(commit)
932  {
933  //Any parameter change?
934  if(value != port->params.adminPathCost)
935  {
936  //The Admin Path Cost parameter is updated using the supplied value
937  port->params.adminPathCost = value;
938 
939  //Writing a value of 0 assigns the automatically calculated default
940  //Path Cost value to the port
942 
943  //The spanning tree priority vectors and port role assignments for
944  //a bridge shall be recomputed by clearing selected and setting
945  //reselect (refer to IEEE Std 802.1D-2004, section 17.13)
946  port->selected = FALSE;
947  port->reselect = TRUE;
948 
949  //Update RSTP state machine
950  rstpFsm(context);
951  }
952  }
953 
954  //Successful processing
955  return NO_ERROR;
956 }
957 
958 
959 /**
960  * @brief Set administrative point-to-point status of the LAN segment
961  * @param[in] context Pointer to the RSTP bridge context
962  * @param[in] portIndex Port index
963  * @param[in] value Administrative point-to-point status of the LAN segment
964  * attached to this port
965  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
966  * value and commits the change if the value is valid. If FALSE, the bridge
967  * only performs the verification and does not take any further action
968  * @return Error code
969  **/
970 
972  uint_t portIndex, RstpAdminPointToPointMac value, bool_t commit)
973 {
975 
976  //Make sure the RSTP bridge context is valid
977  if(context == NULL)
978  return ERROR_WRITE_FAILED;
979 
980  //Invalid port index?
981  if(portIndex < 1 || portIndex > context->numPorts)
982  return ERROR_INVALID_PORT;
983 
984  //Check the value of the parameter
988  {
989  return ERROR_WRONG_VALUE;
990  }
991 
992  //Point to the port that matches the specified port index
993  port = &context->ports[portIndex - 1];
994 
995  //Commit phase?
996  if(commit)
997  {
998  //Any parameter change?
999  if(value != port->params.adminPointToPointMac)
1000  {
1001  //Set the administrative point-to-point status of the LAN segment
1002  //attached to this port
1003  port->params.adminPointToPointMac = value;
1004 
1005  //Update the value of the operPointToPointMac variable
1007 
1008  //Update RSTP state machine
1009  rstpFsm(context);
1010  }
1011  }
1012 
1013  //Successful processing
1014  return NO_ERROR;
1015 }
1016 
1017 
1018 /**
1019  * @brief Set administrative value of the Edge Port parameter
1020  * @param[in] context Pointer to the RSTP bridge context
1021  * @param[in] portIndex Port index
1022  * @param[in] value Administrative value of the Edge Port parameter
1023  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
1024  * value and commits the change if the value is valid. If FALSE, the bridge
1025  * only performs the verification and does not take any further action
1026  * @return Error code
1027  **/
1028 
1030  bool_t value, bool_t commit)
1031 {
1033 
1034  //Make sure the RSTP bridge context is valid
1035  if(context == NULL)
1036  return ERROR_WRITE_FAILED;
1037 
1038  //Invalid port index?
1039  if(portIndex < 1 || portIndex > context->numPorts)
1040  return ERROR_INVALID_PORT;
1041 
1042  //Point to the port that matches the specified port index
1043  port = &context->ports[portIndex - 1];
1044 
1045  //Commit phase?
1046  if(commit)
1047  {
1048  //Any parameter change?
1049  if(value != port->params.adminEdgePort)
1050  {
1051  //A value of true indicates that this port should be assumed as an
1052  //edge-port
1053  port->params.adminEdgePort = value;
1054 
1055  //Update RSTP state machine
1056  port->portEnabled = FALSE;
1057  rstpFsm(context);
1058  port->portEnabled = port->macOperState && port->params.adminPortState;
1059  rstpFsm(context);
1060  }
1061  }
1062 
1063  //Successful processing
1064  return NO_ERROR;
1065 }
1066 
1067 
1068 /**
1069  * @brief Set AutoEdgePort parameter
1070  * @param[in] context Pointer to the RSTP bridge context
1071  * @param[in] portIndex Port index
1072  * @param[in] value AutoEdgePort parameter for the port
1073  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
1074  * value and commits the change if the value is valid. If FALSE, the bridge
1075  * only performs the verification and does not take any further action
1076  * @return Error code
1077  **/
1078 
1080  bool_t value, bool_t commit)
1081 {
1083 
1084  //Make sure the RSTP bridge context is valid
1085  if(context == NULL)
1086  return ERROR_WRITE_FAILED;
1087 
1088  //Invalid port index?
1089  if(portIndex < 1 || portIndex > context->numPorts)
1090  return ERROR_INVALID_PORT;
1091 
1092  //Point to the port that matches the specified port index
1093  port = &context->ports[portIndex - 1];
1094 
1095  //Commit phase?
1096  if(commit)
1097  {
1098  //Any parameter change?
1099  if(value != port->params.autoEdgePort)
1100  {
1101  //Each port be configured to automatically determine if it an edge port
1102  //by setting the AutoEdgePort parameter
1103  port->params.autoEdgePort = value;
1104 
1105  //Update RSTP state machine
1106  rstpFsm(context);
1107  }
1108  }
1109 
1110  //Successful processing
1111  return NO_ERROR;
1112 }
1113 
1114 
1115 /**
1116  * @brief Force protocol migration
1117  * @param[in] context Pointer to the RSTP bridge context
1118  * @param[in] portIndex Port index
1119  * @param[in] value Value of the mcheck parameter. Setting mcheck variable to
1120  * FALSE has no effect
1121  * @param[in] commit If this flag is TRUE, the bridge verifies the parameter
1122  * value and commits the change if the value is valid. If FALSE, the bridge
1123  * only performs the verification and does not take any further action
1124  * @return Error code
1125  **/
1126 
1128  bool_t value, bool_t commit)
1129 {
1131 
1132  //Make sure the RSTP bridge context is valid
1133  if(context == NULL)
1134  return ERROR_WRITE_FAILED;
1135 
1136  //Invalid port index?
1137  if(portIndex < 1 || portIndex > context->numPorts)
1138  return ERROR_INVALID_PORT;
1139 
1140  //Point to the port that matches the specified port index
1141  port = &context->ports[portIndex - 1];
1142 
1143  //Commit phase?
1144  if(commit)
1145  {
1146  //Setting mcheck variable to FALSE has no effect
1147  if(value)
1148  {
1149  //Check whether the bridge is operating in STP compatibility mode
1150  if(stpVersion(context))
1151  {
1152  //Setting mcheck has no effect when stpVersion is TRUE (refer
1153  //IEEE Std 802.1D-2004, section 17.19.13)
1154  }
1155  else
1156  {
1157  //When operating in RSTP mode, writing true to this object forces
1158  //this port to transmit RSTP BPDUs
1159  port->mcheck = TRUE;
1160 
1161  //Update RSTP state machine
1162  rstpFsm(context);
1163  }
1164  }
1165  }
1166 
1167  //Successful processing
1168  return NO_ERROR;
1169 }
1170 
1171 
1172 /**
1173  * @brief Get the MAC address assigned to the port
1174  * @param[in] context Pointer to the RSTP bridge context
1175  * @param[in] portIndex Port index
1176  * @param[out] value MAC address of the individual MAC entity for the port
1177  * @return Error code
1178  **/
1179 
1181  MacAddr *value)
1182 {
1184 
1185  //Check parameters
1186  if(context == NULL || value == NULL)
1187  return ERROR_READ_FAILED;
1188 
1189  //Invalid port index?
1190  if(portIndex < 1 || portIndex > context->numPorts)
1191  return ERROR_INVALID_PORT;
1192 
1193  //Point to the port that matches the specified port index
1194  port = &context->ports[portIndex - 1];
1195 
1196  //Retrieve the MAC address of the individual MAC entity for the port
1197  *value = port->macAddr;
1198 
1199  //Successful processing
1200  return NO_ERROR;
1201 }
1202 
1203 
1204 /**
1205  * @brief Get the priority assigned to the port
1206  * @param[in] context Pointer to the RSTP bridge context
1207  * @param[in] portIndex Port index
1208  * @param[out] value Port priority
1209  * @return Error code
1210  **/
1211 
1213  uint8_t *value)
1214 {
1216 
1217  //Check parameters
1218  if(context == NULL || value == NULL)
1219  return ERROR_READ_FAILED;
1220 
1221  //Invalid port index?
1222  if(portIndex < 1 || portIndex > context->numPorts)
1223  return ERROR_INVALID_PORT;
1224 
1225  //Point to the port that matches the specified port index
1226  port = &context->ports[portIndex - 1];
1227 
1228  //Retrieve the priority assigned to the port
1229  *value = (port->portId & RSTP_PORT_PRIORITY_MASK) >> 8;
1230 
1231  //Successful processing
1232  return NO_ERROR;
1233 }
1234 
1235 
1236 /**
1237  * @brief Get the administrative port state
1238  * @param[in] context Pointer to the RSTP bridge context
1239  * @param[in] portIndex Port index
1240  * @param[out] value Administrative port state
1241  * @return Error code
1242  **/
1243 
1245  bool_t *value)
1246 {
1248 
1249  //Check parameters
1250  if(context == NULL || value == NULL)
1251  return ERROR_READ_FAILED;
1252 
1253  //Invalid port index?
1254  if(portIndex < 1 || portIndex > context->numPorts)
1255  return ERROR_INVALID_PORT;
1256 
1257  //Point to the port that matches the specified port index
1258  port = &context->ports[portIndex - 1];
1259 
1260  //Retrieve the administrative port state
1261  *value = port->params.adminPortState;
1262 
1263  //Successful processing
1264  return NO_ERROR;
1265 }
1266 
1267 
1268 /**
1269  * @brief Get the current MAC operational state
1270  * @param[in] context Pointer to the RSTP bridge context
1271  * @param[in] portIndex Port index
1272  * @param[out] value MAC operational state
1273  * @return Error code
1274  **/
1275 
1277  bool_t *value)
1278 {
1280 
1281  //Check parameters
1282  if(context == NULL || value == NULL)
1283  return ERROR_READ_FAILED;
1284 
1285  //Invalid port index?
1286  if(portIndex < 1 || portIndex > context->numPorts)
1287  return ERROR_INVALID_PORT;
1288 
1289  //Point to the port that matches the specified port index
1290  port = &context->ports[portIndex - 1];
1291 
1292  //Retrieve the operational state of the MAC entity
1293  *value = port->macOperState;
1294 
1295  //Successful processing
1296  return NO_ERROR;
1297 }
1298 
1299 
1300 /**
1301  * @brief Get the administrative port path cost
1302  * @param[in] context Pointer to the RSTP bridge context
1303  * @param[in] portIndex Port index
1304  * @param[out] value Administrative port path cost
1305  * @return Error code
1306  **/
1307 
1309  uint32_t *value)
1310 {
1312 
1313  //Check parameters
1314  if(context == NULL || value == NULL)
1315  return ERROR_READ_FAILED;
1316 
1317  //Invalid port index?
1318  if(portIndex < 1 || portIndex > context->numPorts)
1319  return ERROR_INVALID_PORT;
1320 
1321  //Point to the port that matches the specified port index
1322  port = &context->ports[portIndex - 1];
1323 
1324  //Retrieve the value of the Admin Path Cost parameter
1325  *value = port->params.adminPathCost;
1326 
1327  //Successful processing
1328  return NO_ERROR;
1329 }
1330 
1331 
1332 /**
1333  * @brief Get the current value of the port path cost
1334  * @param[in] context Pointer to the RSTP bridge context
1335  * @param[in] portIndex Port index
1336  * @param[out] value Port path cost
1337  * @return Error code
1338  **/
1339 
1341  uint32_t *value)
1342 {
1344 
1345  //Check parameters
1346  if(context == NULL || value == NULL)
1347  return ERROR_READ_FAILED;
1348 
1349  //Invalid port index?
1350  if(portIndex < 1 || portIndex > context->numPorts)
1351  return ERROR_INVALID_PORT;
1352 
1353  //Point to the port that matches the specified port index
1354  port = &context->ports[portIndex - 1];
1355 
1356  //Retrieve the contribution of this port to the path cost of paths towards
1357  //the spanning tree root which include this port
1358  *value = port->portPathCost;
1359 
1360  //Successful processing
1361  return NO_ERROR;
1362 }
1363 
1364 
1365 /**
1366  * @brief Get the administrative point-to-point status of the LAN segment
1367  * @param[in] context Pointer to the RSTP bridge context
1368  * @param[in] portIndex Port index
1369  * @param[out] value Administrative point-to-point status of the LAN segment
1370  * attached to this port
1371  * @return Error code
1372  **/
1373 
1376 {
1378 
1379  //Check parameters
1380  if(context == NULL || value == NULL)
1381  return ERROR_READ_FAILED;
1382 
1383  //Invalid port index?
1384  if(portIndex < 1 || portIndex > context->numPorts)
1385  return ERROR_INVALID_PORT;
1386 
1387  //Point to the port that matches the specified port index
1388  port = &context->ports[portIndex - 1];
1389 
1390  //Retrieve the administrative point-to-point status of the LAN segment
1391  //attached to this port
1392  *value = port->params.adminPointToPointMac;
1393 
1394  //Successful processing
1395  return NO_ERROR;
1396 }
1397 
1398 
1399 /**
1400  * @brief Get the operational point-to-point status of the LAN segment
1401  * @param[in] context Pointer to the RSTP bridge context
1402  * @param[in] portIndex Port index
1403  * @param[out] value Operational point-to-point status of the LAN segment
1404  * attached to this port
1405  * @return Error code
1406  **/
1407 
1409  uint_t portIndex, bool_t *value)
1410 {
1412 
1413  //Check parameters
1414  if(context == NULL || value == NULL)
1415  return ERROR_READ_FAILED;
1416 
1417  //Invalid port index?
1418  if(portIndex < 1 || portIndex > context->numPorts)
1419  return ERROR_INVALID_PORT;
1420 
1421  //Point to the port that matches the specified port index
1422  port = &context->ports[portIndex - 1];
1423 
1424  //Retrieve the operational point-to-point status of the LAN segment
1425  *value = port->operPointToPointMac;
1426 
1427  //Successful processing
1428  return NO_ERROR;
1429 }
1430 
1431 
1432 /**
1433  * @brief Get the administrative value of the Edge Port parameter
1434  * @param[in] context Pointer to the RSTP bridge context
1435  * @param[in] portIndex Port index
1436  * @param[out] value Administrative value of the Edge Port parameter
1437  * @return Error code
1438  **/
1439 
1441  bool_t *value)
1442 {
1444 
1445  //Check parameters
1446  if(context == NULL || value == NULL)
1447  return ERROR_READ_FAILED;
1448 
1449  //Invalid port index?
1450  if(portIndex < 1 || portIndex > context->numPorts)
1451  return ERROR_INVALID_PORT;
1452 
1453  //Point to the port that matches the specified port index
1454  port = &context->ports[portIndex - 1];
1455 
1456  //A value of true indicates that this port should be assumed as an edge-port
1457  *value = port->params.adminEdgePort;
1458 
1459  //Successful processing
1460  return NO_ERROR;
1461 }
1462 
1463 
1464 /**
1465  * @brief Get the value of the AutoEdgePort parameter
1466  * @param[in] context Pointer to the RSTP bridge context
1467  * @param[in] portIndex Port index
1468  * @param[out] value Value of the AutoEdgePort parameter for the port
1469  * @return Error code
1470  **/
1471 
1473  bool_t *value)
1474 {
1476 
1477  //Check parameters
1478  if(context == NULL || value == NULL)
1479  return ERROR_READ_FAILED;
1480 
1481  //Invalid port index?
1482  if(portIndex < 1 || portIndex > context->numPorts)
1483  return ERROR_INVALID_PORT;
1484 
1485  //Point to the port that matches the specified port index
1486  port = &context->ports[portIndex - 1];
1487 
1488  //Retrieve the value of the AutoEdgePort parameter
1489  *value = port->params.autoEdgePort;
1490 
1491  //Successful processing
1492  return NO_ERROR;
1493 }
1494 
1495 
1496 /**
1497  * @brief Get the operational value of the Edge Port parameter
1498  * @param[in] context Pointer to the RSTP bridge context
1499  * @param[in] portIndex Port index
1500  * @param[out] value Operational value of the Edge Port parameter
1501  * @return Error code
1502  **/
1503 
1505  bool_t *value)
1506 {
1508 
1509  //Check parameters
1510  if(context == NULL || value == NULL)
1511  return ERROR_READ_FAILED;
1512 
1513  //Invalid port index?
1514  if(portIndex < 1 || portIndex > context->numPorts)
1515  return ERROR_INVALID_PORT;
1516 
1517  //Point to the port that matches the specified port index
1518  port = &context->ports[portIndex - 1];
1519 
1520  //Retrieve the operational value of the Edge Port parameter
1521  *value = port->operEdge;
1522 
1523  //Successful processing
1524  return NO_ERROR;
1525 }
1526 
1527 
1528 /**
1529  * @brief Get the current state of the port
1530  * @param[in] context Pointer to the RSTP bridge context
1531  * @param[in] portIndex Port index
1532  * @param[out] value Port state
1533  * @return Error code
1534  **/
1535 
1538 {
1540 
1541  //Check parameters
1542  if(context == NULL || value == NULL)
1543  return ERROR_READ_FAILED;
1544 
1545  //Invalid port index?
1546  if(portIndex < 1 || portIndex > context->numPorts)
1547  return ERROR_INVALID_PORT;
1548 
1549  //Point to the port that matches the specified port index
1550  port = &context->ports[portIndex - 1];
1551 
1552  //Retrieve the port's current state, as defined by application of the
1553  //Spanning Tree Protocol
1554  if(port->pstState == RSTP_PST_STATE_DISCARDING)
1555  {
1556  //Disabled, blocking, listening, and broken all correspond to the
1557  //Discarding port state (refer to IEEE Std 802.1D-2004, section 17.4)
1558  if(!port->params.adminPortState)
1559  {
1560  //Disabled represents exclusion of the port from the active topology
1561  //by management setting of the Administrative Port State to disabled
1563  }
1564  else if(!port->macOperState)
1565  {
1566  //The broken state represents the failure or unavailability of
1567  //the port's MAC as indicated by MAC_Operational FALSE
1569  }
1570  else if(port->role == STP_PORT_ROLE_ALTERNATE ||
1571  port->role == STP_PORT_ROLE_BACKUP)
1572  {
1573  //Blocking represents exclusion of the port from the active topology
1574  //by the spanning tree algorithm (computing an Alternate or Backup
1575  //port role)
1577  }
1578  else if(port->role == STP_PORT_ROLE_ROOT ||
1579  port->role == STP_PORT_ROLE_DESIGNATED)
1580  {
1581  //Listening represents a port that the spanning tree algorithm has
1582  //selected to be part of the active topology (computing a Root or
1583  //Designated port role) but is temporarily discarding frames to
1584  //guard against loops or incorrect learning
1586  }
1587  else
1588  {
1589  //Just for sanity
1591  }
1592  }
1593  else if(port->pstState == RSTP_PST_STATE_LEARNING)
1594  {
1595  //Any port that has learning enabled but forwarding disabled has the
1596  //port state Learning
1598  }
1599  else if(port->pstState == RSTP_PST_STATE_FORWARDING)
1600  {
1601  //A port that both learns and forwards frames has the port state
1602  //Forwarding
1604  }
1605  else
1606  {
1607  //Just for sanity
1609  }
1610 
1611  //Successful processing
1612  return NO_ERROR;
1613 }
1614 
1615 
1616 /**
1617  * @brief Get the assigned role of the port
1618  * @param[in] context Pointer to the RSTP bridge context
1619  * @param[in] portIndex Port index
1620  * @param[out] value Port role
1621  * @return Error code
1622  **/
1623 
1625  StpPortRole *value)
1626 {
1628 
1629  //Check parameters
1630  if(context == NULL || value == NULL)
1631  return ERROR_READ_FAILED;
1632 
1633  //Invalid port index?
1634  if(portIndex < 1 || portIndex > context->numPorts)
1635  return ERROR_INVALID_PORT;
1636 
1637  //Point to the port that matches the specified port index
1638  port = &context->ports[portIndex - 1];
1639 
1640  //Retrieve the assigned port role
1641  *value = port->role;
1642 
1643  //Successful processing
1644  return NO_ERROR;
1645 }
1646 
1647 
1648 /**
1649  * @brief Get the bridge identifier of the designated root bridge
1650  * @param[in] context Pointer to the RSTP bridge context
1651  * @param[in] portIndex Port index
1652  * @param[out] value Bridge identifier
1653  * @return Error code
1654  **/
1655 
1657  uint_t portIndex, StpBridgeId *value)
1658 {
1660 
1661  //Check parameters
1662  if(context == NULL || value == NULL)
1663  return ERROR_READ_FAILED;
1664 
1665  //Invalid port index?
1666  if(portIndex < 1 || portIndex > context->numPorts)
1667  return ERROR_INVALID_PORT;
1668 
1669  //Point to the port that matches the specified port index
1670  port = &context->ports[portIndex - 1];
1671 
1672  //Retrieve the unique Bridge Identifier of the bridge recorded as the Root
1673  //in the Configuration BPDUs transmitted by the Designated Bridge for the
1674  //segment to which the port is attached
1675  *value = port->portPriority.rootBridgeId;
1676 
1677  //Successful processing
1678  return NO_ERROR;
1679 }
1680 
1681 
1682 /**
1683  * @brief Get the designated cost of the port
1684  * @param[in] context Pointer to the RSTP bridge context
1685  * @param[in] portIndex Port index
1686  * @param[out] value Designated cost of the port
1687  * @return Error code
1688  **/
1689 
1691  uint_t portIndex, uint32_t *value)
1692 {
1694 
1695  //Check parameters
1696  if(context == NULL || value == NULL)
1697  return ERROR_READ_FAILED;
1698 
1699  //Invalid port index?
1700  if(portIndex < 1 || portIndex > context->numPorts)
1701  return ERROR_INVALID_PORT;
1702 
1703  //Point to the port that matches the specified port index
1704  port = &context->ports[portIndex - 1];
1705 
1706  //Retrieve the path cost of the Designated Port of the segment connected
1707  //to this port
1708  *value = port->portPriority.rootPathCost;
1709 
1710  //Successful processing
1711  return NO_ERROR;
1712 }
1713 
1714 
1715 /**
1716  * @brief Get the bridge identifier of the designated bridge
1717  * @param[in] context Pointer to the RSTP bridge context
1718  * @param[in] portIndex Port index
1719  * @param[out] value Bridge identifier
1720  * @return Error code
1721  **/
1722 
1724  uint_t portIndex, StpBridgeId *value)
1725 {
1727 
1728  //Check parameters
1729  if(context == NULL || value == NULL)
1730  return ERROR_READ_FAILED;
1731 
1732  //Invalid port index?
1733  if(portIndex < 1 || portIndex > context->numPorts)
1734  return ERROR_INVALID_PORT;
1735 
1736  //Point to the port that matches the specified port index
1737  port = &context->ports[portIndex - 1];
1738 
1739  //Retrieve the Bridge Identifier of the bridge that this port considers to
1740  //be the Designated Bridge for this port's segment
1741  *value = port->portPriority.designatedBridgeId;
1742 
1743  //Successful processing
1744  return NO_ERROR;
1745 }
1746 
1747 
1748 /**
1749  * @brief Get the port identifier of the designated bridge
1750  * @param[in] context Pointer to the RSTP bridge context
1751  * @param[in] portIndex Port index
1752  * @param[out] value Port identifier
1753  * @return Error code
1754  **/
1755 
1757  uint_t portIndex, uint16_t *value)
1758 {
1760 
1761  //Check parameters
1762  if(context == NULL || value == NULL)
1763  return ERROR_READ_FAILED;
1764 
1765  //Invalid port index?
1766  if(portIndex < 1 || portIndex > context->numPorts)
1767  return ERROR_INVALID_PORT;
1768 
1769  //Point to the port that matches the specified port index
1770  port = &context->ports[portIndex - 1];
1771 
1772  //Retrieve the Port Identifier of the port on the Designated Bridge for
1773  //this port's segment
1774  *value = port->portPriority.designatedPortId;
1775 
1776  //Successful processing
1777  return NO_ERROR;
1778 }
1779 
1780 
1781 /**
1782  * @brief Get the number of times the port has transitioned to Forwarding state
1783  * @param[in] context Pointer to the RSTP bridge context
1784  * @param[in] portIndex Port index
1785  * @param[out] value Number of transitions to Forwarding state
1786  * @return Error code
1787  **/
1788 
1790  uint_t portIndex, uint_t *value)
1791 {
1793 
1794  //Check parameters
1795  if(context == NULL || value == NULL)
1796  return ERROR_READ_FAILED;
1797 
1798  //Invalid port index?
1799  if(portIndex < 1 || portIndex > context->numPorts)
1800  return ERROR_INVALID_PORT;
1801 
1802  //Point to the port that matches the specified port index
1803  port = &context->ports[portIndex - 1];
1804 
1805  //Retrieve the number of times this port has transitioned from the Learning
1806  //state to the Forwarding state
1807  *value = port->forwardTransitions;
1808 
1809  //Successful processing
1810  return NO_ERROR;
1811 }
1812 
1813 #endif
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_WRITE_FAILED
Definition: error.h:221
@ ERROR_WRONG_VALUE
Definition: error.h:123
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_READ_FAILED
Definition: error.h:222
@ ERROR_INCONSISTENT_VALUE
Definition: error.h:124
MacAddr
Definition: ethernet.h:195
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
RSTP (Rapid Spanning Tree Protocol)
#define RSTP_MIN_TRANSMIT_HOLD_COUNT
Definition: rstp.h:156
#define RSTP_MIN_BRIDGE_FORWARD_DELAY
Definition: rstp.h:135
#define RSTP_MAX_BRIDGE_FORWARD_DELAY
Definition: rstp.h:149
#define RSTP_MAX_TRANSMIT_HOLD_COUNT
Definition: rstp.h:170
RstpAdminPointToPointMac
Administrative state of the point-to-point status.
Definition: rstp.h:255
@ RSTP_ADMIN_P2P_MAC_FORCE_FALSE
Definition: rstp.h:256
@ RSTP_ADMIN_P2P_MAC_AUTO
Definition: rstp.h:258
@ RSTP_ADMIN_P2P_MAC_FORCE_TRUE
Definition: rstp.h:257
#define RstpBridgeContext
Definition: rstp.h:36
#define RstpBridgePort
Definition: rstp.h:40
#define RSTP_MAX_PORT_PATH_COST
Definition: rstp.h:212
#define RSTP_MAX_BRIDGE_HELLO_TIME
Definition: rstp.h:128
#define RSTP_MAX_BRIDGE_MAX_AGE
Definition: rstp.h:107
#define RSTP_MAX_AGEING_TIME
Definition: rstp.h:191
#define RSTP_PORT_NUM_MASK
Definition: rstp_bpdu.h:44
#define RSTP_PORT_PRIORITY_MASK
Definition: rstp_bpdu.h:43
bool_t stpVersion(RstpBridgeContext *context)
stpVersion condition (17.20.12)
RSTP state machine conditions.
void rstpFsm(RstpBridgeContext *context)
RSTP state machine implementation.
Definition: rstp_fsm.c:152
void rstpFsmInit(RstpBridgeContext *context)
RSTP state machine initialization.
Definition: rstp_fsm.c:49
Rapid Spanning Tree state machines.
error_t rstpMgmtSetProtocolMigration(RstpBridgeContext *context, uint_t portIndex, bool_t value, bool_t commit)
Force protocol migration.
Definition: rstp_mgmt.c:1127
error_t rstpMgmtGetMaxAge(RstpBridgeContext *context, uint_t *value)
Get the current Max Age value.
Definition: rstp_mgmt.c:690
error_t rstpMgmtGetRootPort(RstpBridgeContext *context, uint16_t *value)
Get the current root port.
Definition: rstp_mgmt.c:668
error_t rstpMgmtSetBridgeForwardDelay(RstpBridgeContext *context, uint_t value, bool_t commit)
Set Bridge Forward Delay parameter.
Definition: rstp_mgmt.c:276
error_t rstpMgmtGetNumPorts(RstpBridgeContext *context, uint_t *value)
Get the number of ports.
Definition: rstp_mgmt.c:435
error_t rstpMgmtGetAgeingTime(RstpBridgeContext *context, uint_t *value)
Get the assigned value of the Ageing Time parameter.
Definition: rstp_mgmt.c:604
error_t rstpMgmtSetAgeingTime(RstpBridgeContext *context, uint_t value, bool_t commit)
Set Ageing Time parameter.
Definition: rstp_mgmt.c:391
error_t rstpMgmtGetBridgeMaxAge(RstpBridgeContext *context, uint_t *value)
Get the assigned value of the Bridge Max Age parameter.
Definition: rstp_mgmt.c:520
error_t rstpMgmtGetAdminPointToPointMac(RstpBridgeContext *context, uint_t portIndex, RstpAdminPointToPointMac *value)
Get the administrative point-to-point status of the LAN segment.
Definition: rstp_mgmt.c:1374
error_t rstpMgmtSetAdminEdgePort(RstpBridgeContext *context, uint_t portIndex, bool_t value, bool_t commit)
Set administrative value of the Edge Port parameter.
Definition: rstp_mgmt.c:1029
error_t rstpMgmtGetPortPriority(RstpBridgeContext *context, uint_t portIndex, uint8_t *value)
Get the priority assigned to the port.
Definition: rstp_mgmt.c:1212
error_t rstpMgmtGetBridgeHelloTime(RstpBridgeContext *context, uint_t *value)
Get the assigned value of the Bridge Hello Time parameter.
Definition: rstp_mgmt.c:541
error_t rstpMgmtSetAdminPortState(RstpBridgeContext *context, uint_t portIndex, bool_t value, bool_t commit)
Set administrative bridge port state.
Definition: rstp_mgmt.c:860
error_t rstpMgmtSetAdminPortPathCost(RstpBridgeContext *context, uint_t portIndex, uint32_t value, bool_t commit)
Set administrative port path cost.
Definition: rstp_mgmt.c:910
error_t rstpMgmtGetAdminEdgePort(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the administrative value of the Edge Port parameter.
Definition: rstp_mgmt.c:1440
error_t rstpMgmtSetPortPriority(RstpBridgeContext *context, uint_t portIndex, uint8_t value, bool_t commit)
Set port priority.
Definition: rstp_mgmt.c:804
error_t rstpMgmtGetPortDesignatedCost(RstpBridgeContext *context, uint_t portIndex, uint32_t *value)
Get the designated cost of the port.
Definition: rstp_mgmt.c:1690
error_t rstpMgmtGetMacOperState(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the current MAC operational state.
Definition: rstp_mgmt.c:1276
error_t rstpMgmtSetAdminPointToPointMac(RstpBridgeContext *context, uint_t portIndex, RstpAdminPointToPointMac value, bool_t commit)
Set administrative point-to-point status of the LAN segment.
Definition: rstp_mgmt.c:971
error_t rstpMgmtGetBridgeForwardDelay(RstpBridgeContext *context, uint_t *value)
Get the assigned value of the Bridge Forward Delay parameter.
Definition: rstp_mgmt.c:562
error_t rstpMgmtGetBridgeAddr(RstpBridgeContext *context, MacAddr *value)
Get the MAC address assigned to the bridge.
Definition: rstp_mgmt.c:478
error_t rstpMgmtGetPortPathCost(RstpBridgeContext *context, uint_t portIndex, uint32_t *value)
Get the current value of the port path cost.
Definition: rstp_mgmt.c:1340
error_t rstpMgmtSetBridgeMaxAge(RstpBridgeContext *context, uint_t value, bool_t commit)
Set Bridge Max Age parameter.
Definition: rstp_mgmt.c:156
error_t rstpMgmtGetVersion(RstpBridgeContext *context, uint_t *value)
Get assigned protocol version.
Definition: rstp_mgmt.c:456
error_t rstpMgmtGetTimeSinceTopologyChange(RstpBridgeContext *context, uint_t *value)
Get the time since a topology change was last detected.
Definition: rstp_mgmt.c:778
error_t rstpMgmtGetAdminPortState(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the administrative port state.
Definition: rstp_mgmt.c:1244
error_t rstpMgmtGetPortState(RstpBridgeContext *context, uint_t portIndex, StpPortState *value)
Get the current state of the port.
Definition: rstp_mgmt.c:1536
error_t rstpMgmtGetBridgePriority(RstpBridgeContext *context, uint16_t *value)
Get the assigned bridge priority.
Definition: rstp_mgmt.c:499
error_t rstpMgmtGetTxHoldCount(RstpBridgeContext *context, uint_t *value)
Get the assigned value of the Transmit Hold Count parameter.
Definition: rstp_mgmt.c:583
error_t rstpMgmtSetVersion(RstpBridgeContext *context, uint_t value, bool_t commit)
Set protocol version.
Definition: rstp_mgmt.c:55
error_t rstpMgmtGetPortRole(RstpBridgeContext *context, uint_t portIndex, StpPortRole *value)
Get the assigned role of the port.
Definition: rstp_mgmt.c:1624
error_t rstpMgmtGetHelloTime(RstpBridgeContext *context, uint_t *value)
Get the current Hello Time value.
Definition: rstp_mgmt.c:712
error_t rstpMgmtGetOperEdgePort(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the operational value of the Edge Port parameter.
Definition: rstp_mgmt.c:1504
error_t rstpMgmtGetForwardDelay(RstpBridgeContext *context, uint_t *value)
Get the current Forward Delay value.
Definition: rstp_mgmt.c:735
error_t rstpMgmtGetPortDesignatedRoot(RstpBridgeContext *context, uint_t portIndex, StpBridgeId *value)
Get the bridge identifier of the designated root bridge.
Definition: rstp_mgmt.c:1656
error_t rstpMgmtGetForwardTransitions(RstpBridgeContext *context, uint_t portIndex, uint_t *value)
Get the number of times the port has transitioned to Forwarding state.
Definition: rstp_mgmt.c:1789
error_t rstpMgmtSetAutoEdgePort(RstpBridgeContext *context, uint_t portIndex, bool_t value, bool_t commit)
Set AutoEdgePort parameter.
Definition: rstp_mgmt.c:1079
error_t rstpMgmtGetPortAddr(RstpBridgeContext *context, uint_t portIndex, MacAddr *value)
Get the MAC address assigned to the port.
Definition: rstp_mgmt.c:1180
error_t rstpMgmtGetPortDesignatedPort(RstpBridgeContext *context, uint_t portIndex, uint16_t *value)
Get the port identifier of the designated bridge.
Definition: rstp_mgmt.c:1756
error_t rstpMgmtGetPortDesignatedBridge(RstpBridgeContext *context, uint_t portIndex, StpBridgeId *value)
Get the bridge identifier of the designated bridge.
Definition: rstp_mgmt.c:1723
error_t rstpMgmtSetBridgeHelloTime(RstpBridgeContext *context, uint_t value, bool_t commit)
Set Bridge Hello Time parameter.
Definition: rstp_mgmt.c:216
error_t rstpMgmtSetBridgePriority(RstpBridgeContext *context, uint16_t value, bool_t commit)
Set bridge priority.
Definition: rstp_mgmt.c:96
error_t rstpMgmtGetDesignatedRoot(RstpBridgeContext *context, StpBridgeId *value)
Get the bridge identifier of the root of the spanning tree.
Definition: rstp_mgmt.c:625
error_t rstpMgmtGetAutoEdgePort(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the value of the AutoEdgePort parameter.
Definition: rstp_mgmt.c:1472
error_t rstpMgmtGetAdminPortPathCost(RstpBridgeContext *context, uint_t portIndex, uint32_t *value)
Get the administrative port path cost.
Definition: rstp_mgmt.c:1308
error_t rstpMgmtSetTxHoldCount(RstpBridgeContext *context, uint_t value, bool_t commit)
Set Transmit Hold Count parameter.
Definition: rstp_mgmt.c:339
error_t rstpMgmtGetRootPathCost(RstpBridgeContext *context, uint32_t *value)
Get the current cost of the path to the root.
Definition: rstp_mgmt.c:647
error_t rstpMgmtGetTopologyChanges(RstpBridgeContext *context, uint_t *value)
Get the number of topology changes.
Definition: rstp_mgmt.c:757
error_t rstpMgmtGetOperPointToPointMac(RstpBridgeContext *context, uint_t portIndex, bool_t *value)
Get the operational point-to-point status of the LAN segment.
Definition: rstp_mgmt.c:1408
bool_t rstpCheckBridgeParams(uint_t maxAge, uint_t helloTime, uint_t forwardDelay)
Check bridge parameters.
Definition: rstp_misc.c:854
void rstpUpdateAgeingTime(RstpBridgeContext *context, uint32_t ageingTime)
Set ageing time for dynamic filtering entries.
Definition: rstp_misc.c:527
void rstpUpdateOperPointToPointMac(RstpBridgePort *port)
Update the value of the operPointToPointMac variable.
Definition: rstp_misc.c:455
void rstpUpdatePortPathCost(RstpBridgePort *port)
Update the value of the portPathCost variable.
Definition: rstp_misc.c:425
RSTP helper functions.
@ RSTP_PST_STATE_LEARNING
Definition: rstp_pst.h:50
@ RSTP_PST_STATE_DISCARDING
Definition: rstp_pst.h:49
@ RSTP_PST_STATE_FORWARDING
Definition: rstp_pst.h:51
StpBridgeId
Definition: stp_common.h:148
@ STP_PROTOCOL_VERSION
STP version.
Definition: stp_common.h:97
@ RSTP_PROTOCOL_VERSION
RSTP version.
Definition: stp_common.h:98
StpPortRole
Port role values.
Definition: stp_common.h:123
@ STP_PORT_ROLE_BACKUP
Definition: stp_common.h:128
@ STP_PORT_ROLE_ALTERNATE
Definition: stp_common.h:127
@ STP_PORT_ROLE_ROOT
Definition: stp_common.h:125
@ STP_PORT_ROLE_DESIGNATED
Definition: stp_common.h:126
StpPortState
Port states.
Definition: stp_common.h:108
@ STP_PORT_STATE_BLOCKING
Definition: stp_common.h:111
@ STP_PORT_STATE_LEARNING
Definition: stp_common.h:113
@ STP_PORT_STATE_LISTENING
Definition: stp_common.h:112
@ STP_PORT_STATE_BROKEN
Definition: stp_common.h:110
@ STP_PORT_STATE_FORWARDING
Definition: stp_common.h:114
@ STP_PORT_STATE_DISABLED
Definition: stp_common.h:109
uint8_t value[]
Definition: tcp.h:369