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