xref: /illumos-gate/usr/src/lib/librstp/common/pcost.c (revision eb00b1c8a31c2253a353644606388dff5b0e0275)
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
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
74 updPortPathCost (STATE_MACH_T *this)
75 {
76 }
77 
78 void
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
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