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 /* Path Cost monitoring state machine */
24
25 #include "base.h"
26 #include "stpm.h"
27 #include "stp_to.h" /* for STP_OUT_get_port_oper_speed */
28
29 #define STATES { \
30 CHOOSE(AUTO), \
31 CHOOSE(FORSE), \
32 CHOOSE(STABLE) \
33 }
34
35 #define GET_STATE_NAME STP_pcost_get_state_name
36 #include "choose.h"
37
38 static long
computeAutoPCost(STATE_MACH_T * this)39 computeAutoPCost (STATE_MACH_T *this)
40 {
41 long lret;
42 register PORT_T* port = this->owner.port;
43
44 if (port->usedSpeed < 10L) { /* < 10Mb/s */
45 lret = 20000000;
46 } else if (port->usedSpeed <= 10L) { /* 10 Mb/s */
47 lret = 2000000;
48 } else if (port->usedSpeed <= 100L) { /* 100 Mb/s */
49 lret = 200000;
50 } else if (port->usedSpeed <= 1000L) { /* 1 Gb/s */
51 lret = 20000;
52 } else if (port->usedSpeed <= 10000L) { /* 10 Gb/s */
53 lret = 2000;
54 } else if (port->usedSpeed <= 100000L) { /* 100 Gb/s */
55 lret = 200;
56 } else if (port->usedSpeed <= 1000000L) { /* 1 GTb/s */
57 lret = 20;
58 } else if (port->usedSpeed <= 10000000L) { /* 10 Tb/s */
59 lret = 2;
60 } else /* ??? */ { /* > Tb/s */
61 lret = 1;
62 }
63 #ifdef STP_DBG
64 if (port->pcost->debug) {
65 stp_trace ("usedSpeed=%lu lret=%ld", port->usedSpeed, lret);
66 }
67 #endif
68
69 return lret;
70 }
71
72 /* ARGSUSED */
73 static void
updPortPathCost(STATE_MACH_T * this)74 updPortPathCost (STATE_MACH_T *this)
75 {
76 }
77
78 void
STP_pcost_enter_state(STATE_MACH_T * this)79 STP_pcost_enter_state (STATE_MACH_T *this)
80 {
81 register PORT_T* port = this->owner.port;
82
83 switch (this->State) {
84 case BEGIN:
85 break;
86 case AUTO:
87 port->operSpeed = STP_OUT_get_port_oper_speed (port->port_index);
88 #ifdef STP_DBG
89 if (port->pcost->debug) {
90 stp_trace ("AUTO:operSpeed=%lu", port->operSpeed);
91 }
92 #endif
93 port->usedSpeed = port->operSpeed;
94 port->operPCost = computeAutoPCost (this);
95 break;
96 case FORSE:
97 port->operPCost = port->adminPCost;
98 port->usedSpeed = (unsigned long)-1;
99 break;
100 case STABLE:
101 updPortPathCost (this);
102 break;
103 }
104 }
105
106 Bool
STP_pcost_check_conditions(STATE_MACH_T * this)107 STP_pcost_check_conditions (STATE_MACH_T* this)
108 {
109 register PORT_T* port = this->owner.port;
110
111 switch (this->State) {
112 case BEGIN:
113 return STP_hop_2_state (this, AUTO);
114 case AUTO:
115 return STP_hop_2_state (this, STABLE);
116 case FORSE:
117 return STP_hop_2_state (this, STABLE);
118 case STABLE:
119 if (ADMIN_PORT_PATH_COST_AUTO == port->adminPCost &&
120 port->operSpeed != port->usedSpeed) {
121 return STP_hop_2_state (this, AUTO);
122 }
123
124 if (ADMIN_PORT_PATH_COST_AUTO != port->adminPCost &&
125 port->operPCost != port->adminPCost) {
126 return STP_hop_2_state (this, FORSE);
127 }
128 break;
129 }
130 return False;
131 }
132
133